freeablo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
nuklear.h
Go to the documentation of this file.
1 /*
2  Nuklear - 1.40.8 - public domain
3  no warranty implied; use at your own risk.
4  authored from 2015-2017 by Micha Mettke
5 
6 ABOUT:
7  This is a minimal state graphical user interface single header toolkit
8  written in ANSI C and licensed under public domain.
9  It was designed as a simple embeddable user interface for application and does
10  not have any dependencies, a default renderbackend or OS window and input handling
11  but instead provides a very modular library approach by using simple input state
12  for input and draw commands describing primitive shapes as output.
13  So instead of providing a layered library that tries to abstract over a number
14  of platform and render backends it only focuses on the actual UI.
15 
16 VALUES:
17  - Graphical user interface toolkit
18  - Single header library
19  - Written in C89 (a.k.a. ANSI C or ISO C90)
20  - Small codebase (~18kLOC)
21  - Focus on portability, efficiency and simplicity
22  - No dependencies (not even the standard library if not wanted)
23  - Fully skinnable and customizable
24  - Low memory footprint with total memory control if needed or wanted
25  - UTF-8 support
26  - No global or hidden state
27  - Customizable library modules (you can compile and use only what you need)
28  - Optional font baker and vertex buffer output
29 
30 USAGE:
31  This library is self contained in one single header file and can be used either
32  in header only mode or in implementation mode. The header only mode is used
33  by default when included and allows including this header in other headers
34  and does not contain the actual implementation.
35 
36  The implementation mode requires to define the preprocessor macro
37  NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
38 
39  #define NK_IMPLEMENTATION
40  #include "nuklear.h"
41 
42  Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
43  below in header and implementation mode if you want to use additional functionality
44  or need more control over the library.
45  IMPORTANT: Every time you include "nuklear.h" you have to define the same flags.
46  This is very important not doing it either leads to compiler errors
47  or even worse stack corruptions.
48 
49 FEATURES:
50  - Absolutely no platform dependent code
51  - Memory management control ranging from/to
52  - Ease of use by allocating everything from standard library
53  - Control every byte of memory inside the library
54  - Font handling control ranging from/to
55  - Use your own font implementation for everything
56  - Use this libraries internal font baking and handling API
57  - Drawing output control ranging from/to
58  - Simple shapes for more high level APIs which already have drawing capabilities
59  - Hardware accessible anti-aliased vertex buffer output
60  - Customizable colors and properties ranging from/to
61  - Simple changes to color by filling a simple color table
62  - Complete control with ability to use skinning to decorate widgets
63  - Bendable UI library with widget ranging from/to
64  - Basic widgets like buttons, checkboxes, slider, ...
65  - Advanced widget like abstract comboboxes, contextual menus,...
66  - Compile time configuration to only compile what you need
67  - Subset which can be used if you do not want to link or use the standard library
68  - Can be easily modified to only update on user input instead of frame updates
69 
70 OPTIONAL DEFINES:
71  NK_PRIVATE
72  If defined declares all functions as static, so they can only be accessed
73  inside the file that contains the implementation
74 
75  NK_INCLUDE_FIXED_TYPES
76  If defined it will include header <stdint.h> for fixed sized types
77  otherwise nuklear tries to select the correct type. If that fails it will
78  throw a compiler error and you have to select the correct types yourself.
79  <!> If used needs to be defined for implementation and header <!>
80 
81  NK_INCLUDE_DEFAULT_ALLOCATOR
82  if defined it will include header <stdlib.h> and provide additional functions
83  to use this library without caring for memory allocation control and therefore
84  ease memory management.
85  <!> Adds the standard library with malloc and free so don't define if you
86  don't want to link to the standard library <!>
87  <!> If used needs to be defined for implementation and header <!>
88 
89  NK_INCLUDE_STANDARD_IO
90  if defined it will include header <stdio.h> and provide
91  additional functions depending on file loading.
92  <!> Adds the standard library with fopen, fclose,... so don't define this
93  if you don't want to link to the standard library <!>
94  <!> If used needs to be defined for implementation and header <!>
95 
96  NK_INCLUDE_STANDARD_VARARGS
97  if defined it will include header <stdarg.h> and provide
98  additional functions depending on variable arguments
99  <!> Adds the standard library with va_list and so don't define this if
100  you don't want to link to the standard library<!>
101  <!> If used needs to be defined for implementation and header <!>
102 
103  NK_INCLUDE_VERTEX_BUFFER_OUTPUT
104  Defining this adds a vertex draw command list backend to this
105  library, which allows you to convert queue commands into vertex draw commands.
106  This is mainly if you need a hardware accessible format for OpenGL, DirectX,
107  Vulkan, Metal,...
108  <!> If used needs to be defined for implementation and header <!>
109 
110  NK_INCLUDE_FONT_BAKING
111  Defining this adds `stb_truetype` and `stb_rect_pack` implementation
112  to this library and provides font baking and rendering.
113  If you already have font handling or do not want to use this font handler
114  you don't have to define it.
115  <!> If used needs to be defined for implementation and header <!>
116 
117  NK_INCLUDE_DEFAULT_FONT
118  Defining this adds the default font: ProggyClean.ttf into this library
119  which can be loaded into a font atlas and allows using this library without
120  having a truetype font
121  <!> Enabling this adds ~12kb to global stack memory <!>
122  <!> If used needs to be defined for implementation and header <!>
123 
124  NK_INCLUDE_COMMAND_USERDATA
125  Defining this adds a userdata pointer into each command. Can be useful for
126  example if you want to provide custom shaders depending on the used widget.
127  Can be combined with the style structures.
128  <!> If used needs to be defined for implementation and header <!>
129 
130  NK_BUTTON_TRIGGER_ON_RELEASE
131  Different platforms require button clicks occurring either on buttons being
132  pressed (up to down) or released (down to up).
133  By default this library will react on buttons being pressed, but if you
134  define this it will only trigger if a button is released.
135  <!> If used it is only required to be defined for the implementation part <!>
136 
137  NK_ZERO_COMMAND_MEMORY
138  Defining this will zero out memory for each drawing command added to a
139  drawing queue (inside nk_command_buffer_push). Zeroing command memory
140  is very useful for fast checking (using memcmp) if command buffers are
141  equal and avoid drawing frames when nothing on screen has changed since
142  previous frame.
143 
144  NK_ASSERT
145  If you don't define this, nuklear will use <assert.h> with assert().
146  <!> Adds the standard library so define to nothing of not wanted <!>
147  <!> If used needs to be defined for implementation and header <!>
148 
149  NK_BUFFER_DEFAULT_INITIAL_SIZE
150  Initial buffer size allocated by all buffers while using the default allocator
151  functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't
152  want to allocate the default 4k memory then redefine it.
153  <!> If used needs to be defined for implementation and header <!>
154 
155  NK_MAX_NUMBER_BUFFER
156  Maximum buffer size for the conversion buffer between float and string
157  Under normal circumstances this should be more than sufficient.
158  <!> If used needs to be defined for implementation and header <!>
159 
160  NK_INPUT_MAX
161  Defines the max number of bytes which can be added as text input in one frame.
162  Under normal circumstances this should be more than sufficient.
163  <!> If used it is only required to be defined for the implementation part <!>
164 
165  NK_MEMSET
166  You can define this to 'memset' or your own memset implementation
167  replacement. If not nuklear will use its own version.
168  <!> If used it is only required to be defined for the implementation part <!>
169 
170  NK_MEMCPY
171  You can define this to 'memcpy' or your own memcpy implementation
172  replacement. If not nuklear will use its own version.
173  <!> If used it is only required to be defined for the implementation part <!>
174 
175  NK_SQRT
176  You can define this to 'sqrt' or your own sqrt implementation
177  replacement. If not nuklear will use its own slow and not highly
178  accurate version.
179  <!> If used it is only required to be defined for the implementation part <!>
180 
181  NK_SIN
182  You can define this to 'sinf' or your own sine implementation
183  replacement. If not nuklear will use its own approximation implementation.
184  <!> If used it is only required to be defined for the implementation part <!>
185 
186  NK_COS
187  You can define this to 'cosf' or your own cosine implementation
188  replacement. If not nuklear will use its own approximation implementation.
189  <!> If used it is only required to be defined for the implementation part <!>
190 
191  NK_STRTOD
192  You can define this to `strtod` or your own string to double conversion
193  implementation replacement. If not defined nuklear will use its own
194  imprecise and possibly unsafe version (does not handle nan or infinity!).
195  <!> If used it is only required to be defined for the implementation part <!>
196 
197  NK_DTOA
198  You can define this to `dtoa` or your own double to string conversion
199  implementation replacement. If not defined nuklear will use its own
200  imprecise and possibly unsafe version (does not handle nan or infinity!).
201  <!> If used it is only required to be defined for the implementation part <!>
202 
203  NK_VSNPRINTF
204  If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO`
205  and want to be safe define this to `vsnprintf` on compilers supporting
206  later versions of C or C++. By default nuklear will check for your stdlib version
207  in C as well as compiler version in C++. if `vsnprintf` is available
208  it will define it to `vsnprintf` directly. If not defined and if you have
209  older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
210  <!> If used it is only required to be defined for the implementation part <!>
211 
212  NK_BYTE
213  NK_INT16
214  NK_UINT16
215  NK_INT32
216  NK_UINT32
217  NK_SIZE_TYPE
218  NK_POINTER_TYPE
219  If you compile without NK_USE_FIXED_TYPE then a number of standard types
220  will be selected and compile time validated. If they are incorrect you can
221  define the correct types by overloading these type defines.
222 
223 CREDITS:
224  Developed by Micha Mettke and every direct or indirect contributor.
225 
226  Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain)
227  Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license).
228 
229  Big thank you to Omar Cornut (ocornut@github) for his imgui library and
230  giving me the inspiration for this library, Casey Muratori for handmade hero
231  and his original immediate mode graphical user interface idea and Sean
232  Barret for his amazing single header libraries which restored my faith
233  in libraries and brought me to create some of my own.
234 
235 LICENSE:
236  This software is dual-licensed to the public domain and under the following
237  license: you are granted a perpetual, irrevocable license to copy, modify,
238  publish and distribute this file as you see fit.
239 */
240 #ifndef NK_NUKLEAR_H_
241 #define NK_NUKLEAR_H_
242 
243 #ifdef __cplusplus
244 extern "C" {
245 #endif
246 /*
247  * ==============================================================
248  *
249  * CONSTANTS
250  *
251  * ===============================================================
252  */
253 #define NK_UNDEFINED (-1.0f)
254 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
255 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
256 #ifndef NK_INPUT_MAX
257 #define NK_INPUT_MAX 16
258 #endif
259 #ifndef NK_MAX_NUMBER_BUFFER
260 #define NK_MAX_NUMBER_BUFFER 64
261 #endif
262 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
263 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
264 #endif
265 /*
266  * ==============================================================
267  *
268  * HELPER
269  *
270  * ===============================================================
271  */
272 #ifndef NK_API
273  #ifdef NK_PRIVATE
274  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
275  #define NK_API static inline
276  #elif defined(__cplusplus)
277  #define NK_API static inline
278  #else
279  #define NK_API static
280  #endif
281  #else
282  #define NK_API extern
283  #endif
284 #endif
285 
286 #define NK_INTERN static
287 #define NK_STORAGE static
288 #define NK_GLOBAL static
289 
290 #define NK_FLAG(x) (1 << (x))
291 #define NK_STRINGIFY(x) #x
292 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
293 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
294 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
295 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
296 
297 #ifdef _MSC_VER
298 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
299 #else
300 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
301 #endif
302 
303 #ifndef NK_STATIC_ASSERT
304 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
305 #endif
306 
307 #ifndef NK_FILE_LINE
308 #ifdef _MSC_VER
309 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
310 #else
311 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
312 #endif
313 #endif
314 
315 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
316 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
317 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
318 /*
319  * ===============================================================
320  *
321  * BASIC
322  *
323  * ===============================================================
324  */
325 #ifdef NK_INCLUDE_FIXED_TYPES
326  #include <stdint.h>
327  #define NK_INT8 int8_t
328  #define NK_UINT8 uint8_t
329  #define NK_INT16 int16_t
330  #define NK_UINT16 uint16_t
331  #define NK_INT32 int32_t
332  #define NK_UINT32 uint32_t
333  #define NK_SIZE_TYPE uintptr_t
334  #define NK_POINTER_TYPE uintptr_t
335 #else
336  #ifndef NK_INT8
337  #define NK_INT8 char
338  #endif
339  #ifndef NK_UINT8
340  #define NK_UINT8 unsigned char
341  #endif
342  #ifndef NK_INT16
343  #define NK_INT16 signed short
344  #endif
345  #ifndef NK_UINT16
346  #define NK_UINT16 unsigned short
347  #endif
348  #ifndef NK_INT32
349  #if defined(_MSC_VER)
350  #define NK_INT32 __int32
351  #else
352  #define NK_INT32 signed int
353  #endif
354  #endif
355  #ifndef NK_UINT32
356  #if defined(_MSC_VER)
357  #define NK_UINT32 unsigned __int32
358  #else
359  #define NK_UINT32 unsigned int
360  #endif
361  #endif
362  #ifndef NK_SIZE_TYPE
363  #if defined(_WIN64) && defined(_MSC_VER)
364  #define NK_SIZE_TYPE unsigned __int64
365  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
366  #define NK_SIZE_TYPE unsigned __int32
367  #elif defined(__GNUC__) || defined(__clang__)
368  #if defined(__x86_64__) || defined(__ppc64__)
369  #define NK_SIZE_TYPE unsigned long
370  #else
371  #define NK_SIZE_TYPE unsigned int
372  #endif
373  #else
374  #define NK_SIZE_TYPE unsigned long
375  #endif
376  #endif
377  #ifndef NK_POINTER_TYPE
378  #if defined(_WIN64) && defined(_MSC_VER)
379  #define NK_POINTER_TYPE unsigned __int64
380  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
381  #define NK_POINTER_TYPE unsigned __int32
382  #elif defined(__GNUC__) || defined(__clang__)
383  #if defined(__x86_64__) || defined(__ppc64__)
384  #define NK_POINTER_TYPE unsigned long
385  #else
386  #define NK_POINTER_TYPE unsigned int
387  #endif
388  #else
389  #define NK_POINTER_TYPE unsigned long
390  #endif
391  #endif
392 #endif
393 
394 typedef NK_INT8 nk_char;
399 typedef NK_INT32 nk_int;
403 
404 typedef nk_uint nk_hash;
405 typedef nk_uint nk_flags;
406 typedef nk_uint nk_rune;
407 
408 /* Make sure correct type size:
409  * This will fire with a negative subscript error if the type sizes
410  * are set incorrectly by the compiler, and compile out if not */
411 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
412 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
413 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
414 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
415 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
416 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
417 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
418 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
419 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
420 
421 /* ============================================================================
422  *
423  * API
424  *
425  * =========================================================================== */
426 struct nk_buffer;
427 struct nk_allocator;
428 struct nk_command_buffer;
429 struct nk_draw_command;
430 struct nk_convert_config;
431 struct nk_style_item;
432 struct nk_text_edit;
433 struct nk_draw_list;
434 struct nk_user_font;
435 struct nk_panel;
436 struct nk_context;
437 struct nk_draw_vertex_layout_element;
438 struct nk_style_button;
439 struct nk_style_toggle;
440 struct nk_style_selectable;
441 struct nk_style_slide;
442 struct nk_style_progress;
443 struct nk_style_scrollbar;
444 struct nk_style_edit;
445 struct nk_style_property;
446 struct nk_style_chart;
447 struct nk_style_combo;
448 struct nk_style_tab;
450 struct nk_style_window;
451 
453 struct nk_color {nk_byte r,g,b,a;};
454 struct nk_colorf {float r,g,b,a;};
455 struct nk_vec2 {float x,y;};
456 struct nk_vec2i {short x, y;};
457 struct nk_rect {float x,y,w,h;};
458 struct nk_recti {short x,y,w,h;};
459 typedef char nk_glyph[NK_UTF_SIZE];
460 typedef union {void *ptr; int id;} nk_handle;
461 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
462 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
463 struct nk_scroll {nk_uint x, y;};
464 
477 
478 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
479 typedef void (*nk_plugin_free)(nk_handle, void *old);
480 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
481 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*);
482 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
483 
484 struct nk_allocator {
485  nk_handle userdata;
488 };
504 };
505 /* =============================================================================
506  *
507  * CONTEXT
508  *
509  * =============================================================================*/
510 /* Contexts are the main entry point and the majestro of nuklear and contain all required state.
511  * They are used for window, memory, input, style, stack, commands and time management and need
512  * to be passed into all nuklear GUI specific functions.
513  *
514  * Usage
515  * -------------------
516  * To use a context it first has to be initialized which can be achieved by calling
517  * one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
518  * Each takes in a font handle and a specific way of handling memory. Memory control
519  * hereby ranges from standard library to just specifying a fixed sized block of memory
520  * which nuklear has to manage itself from.
521  *
522  * struct nk_context ctx;
523  * nk_init_xxx(&ctx, ...);
524  * while (1) {
525  * [...]
526  * nk_clear(&ctx);
527  * }
528  * nk_free(&ctx);
529  *
530  * Reference
531  * -------------------
532  * nk_init_default - Initializes context with standard library memory allocation (malloc,free)
533  * nk_init_fixed - Initializes context from single fixed size memory block
534  * nk_init - Initializes context with memory allocator callbacks for alloc and free
535  * nk_init_custom - Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
536  * nk_clear - Called at the end of the frame to reset and prepare the context for the next frame
537  * nk_free - Shutdown and free all memory allocated inside the context
538  * nk_set_user_data - Utility function to pass user data to draw command
539  */
540 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
541 /* nk_init_default - Initializes a `nk_context` struct with a default standard library allocator.
542  * Should be used if you don't want to be bothered with memory management in nuklear.
543  * Parameters:
544  * @ctx must point to an either stack or heap allocated `nk_context` struct
545  * @font must point to a previously initialized font handle for more info look at font documentation
546  * Return values:
547  * true(1) on success
548  * false(0) on failure */
549 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
550 #endif
551 /* nk_init_fixed - Initializes a `nk_context` struct from a single fixed size memory block
552  * Should be used if you want complete control over nuklear's memory management.
553  * Especially recommended for system with little memory or systems with virtual memory.
554  * For the later case you can just allocate for example 16MB of virtual memory
555  * and only the required amount of memory will actually be committed.
556  * IMPORTANT: make sure the passed memory block is aligned correctly for `nk_draw_commands`
557  * Parameters:
558  * @ctx must point to an either stack or heap allocated `nk_context` struct
559  * @memory must point to a previously allocated memory block
560  * @size must contain the total size of @memory
561  * @font must point to a previously initialized font handle for more info look at font documentation
562  * Return values:
563  * true(1) on success
564  * false(0) on failure */
565 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
566 /* nk_init - Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
567  * memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
568  * interface to nuklear. Can be useful for cases like monitoring memory consumption.
569  * Parameters:
570  * @ctx must point to an either stack or heap allocated `nk_context` struct
571  * @alloc must point to a previously allocated memory allocator
572  * @font must point to a previously initialized font handle for more info look at font documentation
573  * Return values:
574  * true(1) on success
575  * false(0) on failure */
576 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
577 /* nk_init_custom - Initializes a `nk_context` struct from two different either fixed or growing
578  * buffers. The first buffer is for allocating draw commands while the second buffer is
579  * used for allocating windows, panels and state tables.
580  * Parameters:
581  * @ctx must point to an either stack or heap allocated `nk_context` struct
582  * @cmds must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
583  * @pool must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
584  * @font must point to a previously initialized font handle for more info look at font documentation
585  * Return values:
586  * true(1) on success
587  * false(0) on failure */
588 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
589 /* nk_clear - Resets the context state at the end of the frame. This includes mostly
590  * garbage collector tasks like removing windows or table not called and therefore
591  * used anymore.
592  * Parameters:
593  * @ctx must point to a previously initialized `nk_context` struct */
594 NK_API void nk_clear(struct nk_context*);
595 /* nk_free - Frees all memory allocated by nuklear. Not needed if context was
596  * initialized with `nk_init_fixed`.
597  * Parameters:
598  * @ctx must point to a previously initialized `nk_context` struct */
599 NK_API void nk_free(struct nk_context*);
600 #ifdef NK_INCLUDE_COMMAND_USERDATA
601 /* nk_set_user_data - Sets the currently passed userdata passed down into each draw command.
602  * Parameters:
603  * @ctx must point to a previously initialized `nk_context` struct
604  * @data handle with either pointer or index to be passed into every draw commands */
605 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
606 #endif
607 /* =============================================================================
608  *
609  * INPUT
610  *
611  * =============================================================================*/
612 /* The input API is responsible for holding the current input state composed of
613  * mouse, key and text input states.
614  * It is worth noting that no direct os or window handling is done in nuklear.
615  * Instead all input state has to be provided by platform specific code. This in one hand
616  * expects more work from the user and complicates usage but on the other hand
617  * provides simple abstraction over a big number of platforms, libraries and other
618  * already provided functionality.
619  *
620  * Usage
621  * -------------------
622  * Input state needs to be provided to nuklear by first calling `nk_input_begin`
623  * which resets internal state like delta mouse position and button transistions.
624  * After `nk_input_begin` all current input state needs to be provided. This includes
625  * mouse motion, button and key pressed and released, text input and scrolling.
626  * Both event- or state-based input handling are supported by this API
627  * and should work without problems. Finally after all input state has been
628  * mirrored `nk_input_end` needs to be called to finish input process.
629  *
630  * struct nk_context ctx;
631  * nk_init_xxx(&ctx, ...);
632  * while (1) {
633  * Event evt;
634  * nk_input_begin(&ctx);
635  * while (GetEvent(&evt)) {
636  * if (evt.type == MOUSE_MOVE)
637  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
638  * else if (evt.type == ...) {
639  * ...
640  * }
641  * }
642  * nk_input_end(&ctx);
643  * [...]
644  * nk_clear(&ctx);
645  * }
646  * nk_free(&ctx);
647  *
648  * Reference
649  * -------------------
650  * nk_input_begin - Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
651  * nk_input_motion - Mirrors mouse cursor position
652  * nk_input_key - Mirrors key state with either pressed or released
653  * nk_input_button - Mirrors mouse button state with either pressed or released
654  * nk_input_scroll - Mirrors mouse scroll values
655  * nk_input_char - Adds a single ASCII text character into an internal text buffer
656  * nk_input_glyph - Adds a single multi-byte UTF-8 character into an internal text buffer
657  * nk_input_unicode - Adds a single unicode rune into an internal text buffer
658  * nk_input_end - Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call
659  */
660 enum nk_keys {
675  /* Shortcuts: text field */
688  /* Shortcuts: scrollbar */
694 };
701 };
702 /* nk_input_begin - Begins the input mirroring process by resetting text, scroll
703  * mouse previous mouse position and movement as well as key state transitions,
704  * Parameters:
705  * @ctx must point to an previously initialized `nk_context` struct */
706 NK_API void nk_input_begin(struct nk_context*);
707 /* nk_input_motion - Mirrors current mouse position to nuklear
708  * Parameters:
709  * @ctx must point to an previously initialized `nk_context` struct
710  * @x must contain an integer describing the current mouse cursor x-position
711  * @y must contain an integer describing the current mouse cursor y-position */
712 NK_API void nk_input_motion(struct nk_context*, int x, int y);
713 /* nk_input_key - Mirrors state of a specific key to nuklear
714  * Parameters:
715  * @ctx must point to an previously initialized `nk_context` struct
716  * @key must be any value specified in enum `nk_keys` that needs to be mirrored
717  * @down must be 0 for key is up and 1 for key is down */
718 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
719 /* nk_input_button - Mirrors the state of a specific mouse button to nuklear
720  * Parameters:
721  * @ctx must point to an previously initialized `nk_context` struct
722  * @nk_buttons must be any value specified in enum `nk_buttons` that needs to be mirrored
723  * @x must contain an integer describing mouse cursor x-position on click up/down
724  * @y must contain an integer describing mouse cursor y-position on click up/down
725  * @down must be 0 for key is up and 1 for key is down */
726 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
727 /* nk_input_scroll - Copies the last mouse scroll value to nuklear. Is generally
728  * a scroll value. So does not have to come from mouse and could also originate
729  * from touch for example.
730  * Parameters:
731  * @ctx must point to an previously initialized `nk_context` struct
732  * @val vector with both X- as well as Y-scroll value */
733 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
734 /* nk_input_char - Copies a single ASCII character into an internal text buffer
735  * This is basically a helper function to quickly push ASCII characters into
736  * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
737  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
738  * Parameters:
739  * @ctx must point to an previously initialized `nk_context` struct
740  * @c must be a single ASCII character preferable one that can be printed */
741 NK_API void nk_input_char(struct nk_context*, char);
742 /* nk_input_unicode - Converts a encoded unicode rune into UTF-8 and copies the result
743  * into an internal text buffer.
744  * Note that you can only push up to NK_INPUT_MAX bytes into
745  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
746  * Parameters:
747  * @ctx must point to an previously initialized `nk_context` struct
748  * @glyph UTF-32 unicode codepoint */
749 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
750 /* nk_input_unicode - Converts a unicode rune into UTF-8 and copies the result
751  * into an internal text buffer.
752  * Note that you can only push up to NK_INPUT_MAX bytes into
753  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
754  * Parameters:
755  * @ctx must point to an previously initialized `nk_context` struct
756  * @glyph UTF-32 unicode codepoint */
757 NK_API void nk_input_unicode(struct nk_context*, nk_rune);
758 /* nk_input_end - End the input mirroring process by resetting mouse grabbing
759  * state to ensure the mouse cursor is not grabbed indefinitely.
760  * Parameters:
761  * @ctx must point to an previously initialized `nk_context` struct */
762 NK_API void nk_input_end(struct nk_context*);
763 /* =============================================================================
764  *
765  * DRAWING
766  *
767  * =============================================================================*/
768 /* This library was designed to be render backend agnostic so it does
769  * not draw anything to screen directly. Instead all drawn shapes, widgets
770  * are made of, are buffered into memory and make up a command queue.
771  * Each frame therefore fills the command buffer with draw commands
772  * that then need to be executed by the user and his own render backend.
773  * After that the command buffer needs to be cleared and a new frame can be
774  * started. It is probably important to note that the command buffer is the main
775  * drawing API and the optional vertex buffer API only takes this format and
776  * converts it into a hardware accessible format.
777  *
778  * Usage
779  * -------------------
780  * To draw all draw commands accumulated over a frame you need your own render
781  * backend able to draw a number of 2D primitives. This includes at least
782  * filled and stroked rectangles, circles, text, lines, triangles and scissors.
783  * As soon as this criterion is met you can iterate over each draw command
784  * and execute each draw command in a interpreter like fashion:
785  *
786  * const struct nk_command *cmd = 0;
787  * nk_foreach(cmd, &ctx) {
788  * switch (cmd->type) {
789  * case NK_COMMAND_LINE:
790  * your_draw_line_function(...)
791  * break;
792  * case NK_COMMAND_RECT
793  * your_draw_rect_function(...)
794  * break;
795  * case ...:
796  * [...]
797  * }
798  *
799  * In program flow context draw commands need to be executed after input has been
800  * gathered and the complete UI with windows and their contained widgets have
801  * been executed and before calling `nk_clear` which frees all previously
802  * allocated draw commands.
803  *
804  * struct nk_context ctx;
805  * nk_init_xxx(&ctx, ...);
806  * while (1) {
807  * Event evt;
808  * nk_input_begin(&ctx);
809  * while (GetEvent(&evt)) {
810  * if (evt.type == MOUSE_MOVE)
811  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
812  * else if (evt.type == [...]) {
813  * [...]
814  * }
815  * }
816  * nk_input_end(&ctx);
817  *
818  * [...]
819  *
820  * const struct nk_command *cmd = 0;
821  * nk_foreach(cmd, &ctx) {
822  * switch (cmd->type) {
823  * case NK_COMMAND_LINE:
824  * your_draw_line_function(...)
825  * break;
826  * case NK_COMMAND_RECT
827  * your_draw_rect_function(...)
828  * break;
829  * case ...:
830  * [...]
831  * }
832  * nk_clear(&ctx);
833  * }
834  * nk_free(&ctx);
835  *
836  * You probably noticed that you have to draw all of the UI each frame which is
837  * quite wasteful. While the actual UI updating loop is quite fast rendering
838  * without actually needing it is not. So there are multiple things you could do.
839  *
840  * First is only update on input. This of course is only an option if your
841  * application only depends on the UI and does not require any outside calculations.
842  * If you actually only update on input make sure to update the UI two times each
843  * frame and call `nk_clear` directly after the first pass and only draw in
844  * the second pass. In addition it is recommended to also add additional timers
845  * to make sure the UI is not drawn more than a fixed number of frames per second.
846  *
847  * struct nk_context ctx;
848  * nk_init_xxx(&ctx, ...);
849  * while (1) {
850  * [...wait for input ]
851  *
852  * [...do two UI passes ...]
853  * do_ui(...)
854  * nk_clear(&ctx);
855  * do_ui(...)
856  *
857  * const struct nk_command *cmd = 0;
858  * nk_foreach(cmd, &ctx) {
859  * switch (cmd->type) {
860  * case NK_COMMAND_LINE:
861  * your_draw_line_function(...)
862  * break;
863  * case NK_COMMAND_RECT
864  * your_draw_rect_function(...)
865  * break;
866  * case ...:
867  * [...]
868  * }
869  * nk_clear(&ctx);
870  * }
871  * nk_free(&ctx);
872  *
873  * The second probably more applicable trick is to only draw if anything changed.
874  * It is not really useful for applications with continuous draw loop but
875  * quite useful for desktop applications. To actually get nuklear to only
876  * draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
877  * allocate a memory buffer that will store each unique drawing output.
878  * After each frame you compare the draw command memory inside the library
879  * with your allocated buffer by memcmp. If memcmp detects differences
880  * you have to copy the command buffer into the allocated buffer
881  * and then draw like usual (this example uses fixed memory but you could
882  * use dynamically allocated memory).
883  *
884  * [... other defines ...]
885  * #define NK_ZERO_COMMAND_MEMORY
886  * #include "nuklear.h"
887  *
888  * struct nk_context ctx;
889  * void *last = calloc(1,64*1024);
890  * void *buf = calloc(1,64*1024);
891  * nk_init_fixed(&ctx, buf, 64*1024);
892  * while (1) {
893  * [...input...]
894  * [...ui...]
895  *
896  * void *cmds = nk_buffer_memory(&ctx.memory);
897  * if (memcmp(cmds, last, ctx.memory.allocated)) {
898  * memcpy(last,cmds,ctx.memory.allocated);
899  * const struct nk_command *cmd = 0;
900  * nk_foreach(cmd, &ctx) {
901  * switch (cmd->type) {
902  * case NK_COMMAND_LINE:
903  * your_draw_line_function(...)
904  * break;
905  * case NK_COMMAND_RECT
906  * your_draw_rect_function(...)
907  * break;
908  * case ...:
909  * [...]
910  * }
911  * }
912  * }
913  * nk_clear(&ctx);
914  * }
915  * nk_free(&ctx);
916  *
917  * Finally while using draw commands makes sense for higher abstracted platforms like
918  * X11 and Win32 or drawing libraries it is often desirable to use graphics
919  * hardware directly. Therefore it is possible to just define
920  * `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
921  * To access the vertex output you first have to convert all draw commands into
922  * vertexes by calling `nk_convert` which takes in your preferred vertex format.
923  * After successfully converting all draw commands just iterate over and execute all
924  * vertex draw commands:
925  *
926  * struct nk_convert_config cfg = {};
927  * static const struct nk_draw_vertex_layout_element vertex_layout[] = {
928  * {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
929  * {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
930  * {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
931  * {NK_VERTEX_LAYOUT_END}
932  * };
933  * cfg.shape_AA = NK_ANTI_ALIASING_ON;
934  * cfg.line_AA = NK_ANTI_ALIASING_ON;
935  * cfg.vertex_layout = vertex_layout;
936  * cfg.vertex_size = sizeof(struct your_vertex);
937  * cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
938  * cfg.circle_segment_count = 22;
939  * cfg.curve_segment_count = 22;
940  * cfg.arc_segment_count = 22;
941  * cfg.global_alpha = 1.0f;
942  * cfg.null = dev->null;
943  *
944  * struct nk_buffer cmds, verts, idx;
945  * nk_buffer_init_default(&cmds);
946  * nk_buffer_init_default(&verts);
947  * nk_buffer_init_default(&idx);
948  * nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
949  * nk_draw_foreach(cmd, &ctx, &cmds) {
950  * if (!cmd->elem_count) continue;
951  * [...]
952  * }
953  * nk_buffer_free(&cms);
954  * nk_buffer_free(&verts);
955  * nk_buffer_free(&idx);
956  *
957  * Reference
958  * -------------------
959  * nk__begin - Returns the first draw command in the context draw command list to be drawn
960  * nk__next - Increments the draw command iterator to the next command inside the context draw command list
961  * nk_foreach - Iterates over each draw command inside the context draw command list
962  *
963  * nk_convert - Converts from the abstract draw commands list into a hardware accessible vertex format
964  * nk__draw_begin - Returns the first vertex command in the context vertex draw list to be executed
965  * nk__draw_next - Increments the vertex command iterator to the next command inside the context vertex command list
966  * nk__draw_end - Returns the end of the vertex draw list
967  * nk_draw_foreach - Iterates over each vertex draw command inside the vertex draw list
968  */
976 };
978  nk_handle texture; /* texture handle to a texture with a white pixel */
979  struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
980 };
982  float global_alpha; /* global alpha value */
983  enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
984  enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
985  unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
986  unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
987  unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
988  struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
989  const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
990  nk_size vertex_size; /* sizeof one vertex for vertex packing */
991  nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
992 };
993 /* nk__begin - Returns a draw command list iterator to iterate all draw
994  * commands accumulated over one frame.
995  * Parameters:
996  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
997  * Return values:
998  * draw command pointer pointing to the first command inside the draw command list */
999 NK_API const struct nk_command* nk__begin(struct nk_context*);
1000 /* nk__next - Returns a draw command list iterator to iterate all draw
1001  * Parameters:
1002  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1003  * @cmd must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1004  * Return values:
1005  * draw command pointer pointing to the next command inside the draw command list */
1006 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1007 /* nk_foreach - Iterates over each draw command inside the context draw command list
1008  * Parameters:
1009  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1010  * @cmd pointer initialized to NULL */
1011 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1012 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1013 /* nk_convert - converts all internal draw command into vertex draw commands and fills
1014  * three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
1015  * as well as some other configuration values have to be configured by filling out a
1016  * `nk_convert_config` struct.
1017  * Parameters:
1018  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1019  * @cmds must point to a previously initialized buffer to hold converted vertex draw commands
1020  * @vertices must point to a previously initialized buffer to hold all produced vertices
1021  * @elements must point to a previously initialized buffer to hold all produced vertex indices
1022  * @config must point to a filled out `nk_config` struct to configure the conversion process
1023  * Returns:
1024  * returns NK_CONVERT_SUCCESS on success and a enum nk_convert_result error values if not */
1025 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1026 /* nk__draw_begin - Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer
1027  * Parameters:
1028  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1029  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1030  * Return values:
1031  * vertex draw command pointer pointing to the first command inside the vertex draw command buffer */
1032 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1033 /* nk__draw_end - Returns the vertex draw command at the end of the vertex draw command buffer
1034  * Parameters:
1035  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1036  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1037  * Return values:
1038  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1039 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1040 /* nk__draw_next - Increments the vertex draw command buffer iterator
1041  * Parameters:
1042  * @cmd must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1043  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1044  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1045  * Return values:
1046  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1047 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1048 /* nk_draw_foreach - Iterates over each vertex draw command inside a vertex draw command buffer
1049  * Parameters:
1050  * @cmd nk_draw_command pointer set to NULL
1051  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1052  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame */
1053 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1054 #endif
1055 /* =============================================================================
1056  *
1057  * WINDOW
1058  *
1059  * =============================================================================
1060  * Windows are the main persistent state used inside nuklear and are life time
1061  * controlled by simply "retouching" (i.e. calling) each window each frame.
1062  * All widgets inside nuklear can only be added inside function pair `nk_begin_xxx`
1063  * and `nk_end`. Calling any widgets outside these two functions will result in an
1064  * assert in debug or no state change in release mode.
1065  *
1066  * Each window holds frame persistent state like position, size, flags, state tables,
1067  * and some garbage collected internal persistent widget state. Each window
1068  * is linked into a window stack list which determines the drawing and overlapping
1069  * order. The topmost window thereby is the currently active window.
1070  *
1071  * To change window position inside the stack occurs either automatically by
1072  * user input by being clicked on or programmatically by calling `nk_window_focus`.
1073  * Windows by default are visible unless explicitly being defined with flag
1074  * `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1075  * `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1076  * `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.
1077  *
1078  * Usage
1079  * -------------------
1080  * To create and keep a window you have to call one of the two `nk_begin_xxx`
1081  * functions to start window declarations and `nk_end` at the end. Furthermore it
1082  * is recommended to check the return value of `nk_begin_xxx` and only process
1083  * widgets inside the window if the value is not 0. Either way you have to call
1084  * `nk_end` at the end of window declarations. Furthermore, do not attempt to
1085  * nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1086  * in a segmentation fault.
1087  *
1088  * if (nk_begin_xxx(...) {
1089  * [... widgets ...]
1090  * }
1091  * nk_end(ctx);
1092  *
1093  * In the grand concept window and widget declarations need to occur after input
1094  * handling and before drawing to screen. Not doing so can result in higher
1095  * latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1096  * is called at the end of the frame. While nuklear's default platform backends
1097  * already call `nk_clear` for you if you write your own backend not calling
1098  * `nk_clear` can cause asserts or even worse undefined behavior.
1099  *
1100  * struct nk_context ctx;
1101  * nk_init_xxx(&ctx, ...);
1102  * while (1) {
1103  * Event evt;
1104  * nk_input_begin(&ctx);
1105  * while (GetEvent(&evt)) {
1106  * if (evt.type == MOUSE_MOVE)
1107  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1108  * else if (evt.type == [...]) {
1109  * nk_input_xxx(...);
1110  * }
1111  * }
1112  * nk_input_end(&ctx);
1113  *
1114  * if (nk_begin_xxx(...) {
1115  * [...]
1116  * }
1117  * nk_end(ctx);
1118  *
1119  * const struct nk_command *cmd = 0;
1120  * nk_foreach(cmd, &ctx) {
1121  * case NK_COMMAND_LINE:
1122  * your_draw_line_function(...)
1123  * break;
1124  * case NK_COMMAND_RECT
1125  * your_draw_rect_function(...)
1126  * break;
1127  * case ...:
1128  * [...]
1129  * }
1130  * nk_clear(&ctx);
1131  * }
1132  * nk_free(&ctx);
1133  *
1134  * Reference
1135  * -------------------
1136  * nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1137  * nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title
1138  * nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1139  *
1140  * nk_window_find - finds and returns the window with give name
1141  * nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1142  * nk_window_get_position - returns the position of the currently processed window
1143  * nk_window_get_size - returns the size with width and height of the currently processed window
1144  * nk_window_get_width - returns the width of the currently processed window
1145  * nk_window_get_height - returns the height of the currently processed window
1146  * nk_window_get_panel - returns the underlying panel which contains all processing state of the current window
1147  * nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window
1148  * nk_window_get_content_region_min - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1149  * nk_window_get_content_region_max - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1150  * nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1151  * nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1152  *
1153  * nk_window_has_focus - returns if the currently processed window is currently active
1154  * nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1155  * nk_window_is_closed - returns if the currently processed window was closed
1156  * nk_window_is_hidden - returns if the currently processed window was hidden
1157  * nk_window_is_active - same as nk_window_has_focus for some reason
1158  * nk_window_is_hovered - returns if the currently processed window is currently being hovered by mouse
1159  * nk_window_is_any_hovered - return if any window currently hovered
1160  * nk_item_is_any_active - returns if any window or widgets is currently hovered or active
1161  *
1162  * nk_window_set_bounds - updates position and size of the currently processed window
1163  * nk_window_set_position - updates position of the currently process window
1164  * nk_window_set_size - updates the size of the currently processed window
1165  * nk_window_set_focus - set the currently processed window as active window
1166  *
1167  * nk_window_close - closes the window with given window name which deletes the window at the end of the frame
1168  * nk_window_collapse - collapses the window with given window name
1169  * nk_window_collapse_if - collapses the window with given window name if the given condition was met
1170  * nk_window_show - hides a visible or reshows a hidden window
1171  * nk_window_show_if - hides/shows a window depending on condition
1172  */
1174  NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */
1175  NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */
1176  NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */
1177  NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */
1178  NK_WINDOW_MINIMIZABLE = NK_FLAG(4), /* adds a minimize icon into the header */
1179  NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), /* Removes the scrollbar from the window */
1180  NK_WINDOW_TITLE = NK_FLAG(6), /* Forces a header at the top at the window showing the title */
1181  NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */
1182  NK_WINDOW_BACKGROUND = NK_FLAG(8), /* Always keep window in the background */
1183  NK_WINDOW_SCALE_LEFT = NK_FLAG(9), /* Puts window scaler in the left-ottom corner instead right-bottom*/
1184  NK_WINDOW_NO_INPUT = NK_FLAG(10) /* Prevents window of scaling, moving or getting focus */
1185 };
1186 /* nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1187  * Parameters:
1188  * @ctx must point to an previously initialized `nk_context` struct
1189  * @title window title and identifier. Needs to be persistent over frames to identify the window
1190  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1191  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1192  * Return values:
1193  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise for example if minimized `*/
1194 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1195 /* nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title
1196  * Parameters:
1197  * @ctx must point to an previously initialized `nk_context` struct
1198  * @name window identifier. Needs to be persistent over frames to identify the window
1199  * @title window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1200  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1201  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1202  * Return values:
1203  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise `*/
1204 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1205 /* nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1206  * All widget calls after this functions will result in asserts or no state changes
1207  * Parameters:
1208  * @ctx must point to an previously initialized `nk_context` struct */
1209 NK_API void nk_end(struct nk_context *ctx);
1210 /* nk_window_find - finds and returns the window with give name
1211  * Parameters:
1212  * @ctx must point to an previously initialized `nk_context` struct
1213  * @name window identifier
1214  * Return values:
1215  * returns a `nk_window` struct pointing to the identified window or 0 if no window with given name was found */
1216 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1217 /* nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1218  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1219  * Parameters:
1220  * @ctx must point to an previously initialized `nk_context` struct
1221  * Return values:
1222  * returns a `nk_rect` struct with window upper left position and size */
1224 /* nk_window_get_position - returns the position of the currently processed window.
1225  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1226  * Parameters:
1227  * @ctx must point to an previously initialized `nk_context` struct
1228  * Return values:
1229  * returns a `nk_vec2` struct with window upper left position */
1231 /* nk_window_get_size - returns the size with width and height of the currently processed window.
1232  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1233  * Parameters:
1234  * @ctx must point to an previously initialized `nk_context` struct
1235  * Return values:
1236  * returns a `nk_vec2` struct with window size */
1238 /* nk_window_get_width - returns the width of the currently processed window.
1239  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1240  * Parameters:
1241  * @ctx must point to an previously initialized `nk_context` struct
1242  * Return values:
1243  * returns the window width */
1244 NK_API float nk_window_get_width(const struct nk_context*);
1245 /* nk_window_get_height - returns the height of the currently processed window.
1246  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1247  * Parameters:
1248  * @ctx must point to an previously initialized `nk_context` struct
1249  * Return values:
1250  * returns the window height */
1251 NK_API float nk_window_get_height(const struct nk_context*);
1252 /* nk_window_get_panel - returns the underlying panel which contains all processing state of the current window.
1253  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1254  * Parameters:
1255  * @ctx must point to an previously initialized `nk_context` struct
1256  * Return values:
1257  * returns a pointer to window internal `nk_panel` state. DO NOT keep this pointer around it is only valid until `nk_end` */
1259 /* nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window.
1260  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1261  * Parameters:
1262  * @ctx must point to an previously initialized `nk_context` struct
1263  * Return values:
1264  * returns `nk_rect` struct with screen position and size (no scrollbar offset) of the visible space inside the current window */
1266 /* nk_window_get_content_region_min - returns the upper left position of the currently visible and non-clipped space inside the currently processed window.
1267  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1268  * Parameters:
1269  * @ctx must point to an previously initialized `nk_context` struct
1270  * Return values:
1271  * returns `nk_vec2` struct with upper left screen position (no scrollbar offset) of the visible space inside the current window */
1273 /* nk_window_get_content_region_max - returns the lower right screen position of the currently visible and non-clipped space inside the currently processed window.
1274  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1275  * Parameters:
1276  * @ctx must point to an previously initialized `nk_context` struct
1277  * Return values:
1278  * returns `nk_vec2` struct with lower right screen position (no scrollbar offset) of the visible space inside the current window */
1280 /* nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1281  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1282  * Parameters:
1283  * @ctx must point to an previously initialized `nk_context` struct
1284  * Return values:
1285  * returns `nk_vec2` struct with size the visible space inside the current window */
1287 /* nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1288  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1289  * Parameters:
1290  * @ctx must point to an previously initialized `nk_context` struct
1291  * Return values:
1292  * returns a pointer to window internal `nk_command_buffer` struct used as drawing canvas. Can be used to do custom drawing */
1294 /* nk_window_has_focus - returns if the currently processed window is currently active
1295  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1296  * Parameters:
1297  * @ctx must point to an previously initialized `nk_context` struct
1298  * Return values:
1299  * returns 0 if current window is not active or 1 if it is */
1300 NK_API int nk_window_has_focus(const struct nk_context*);
1301 /* nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1302  * Parameters:
1303  * @ctx must point to an previously initialized `nk_context` struct
1304  * @name of window you want to check is collapsed
1305  * Return values:
1306  * returns 1 if current window is minimized and 0 if window not found or is not minimized */
1307 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1308 /* nk_window_is_closed - returns if the window with given name was closed by calling `nk_close`
1309  * Parameters:
1310  * @ctx must point to an previously initialized `nk_context` struct
1311  * @name of window you want to check is closed
1312  * Return values:
1313  * returns 1 if current window was closed or 0 window not found or not closed */
1314 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1315 /* nk_window_is_hidden - returns if the window with given name is hidden
1316  * Parameters:
1317  * @ctx must point to an previously initialized `nk_context` struct
1318  * @name of window you want to check is hidden
1319  * Return values:
1320  * returns 1 if current window is hidden or 0 window not found or visible */
1321 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1322 /* nk_window_is_active - same as nk_window_has_focus for some reason
1323  * Parameters:
1324  * @ctx must point to an previously initialized `nk_context` struct
1325  * @name of window you want to check is hidden
1326  * Return values:
1327  * returns 1 if current window is active or 0 window not found or not active */
1328 NK_API int nk_window_is_active(struct nk_context*, const char*);
1329 /* nk_window_is_hovered - return if the current window is being hovered
1330  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1331  * Parameters:
1332  * @ctx must point to an previously initialized `nk_context` struct
1333  * Return values:
1334  * returns 1 if current window is hovered or 0 otherwise */
1336 /* nk_window_is_any_hovered - returns if the any window is being hovered
1337  * Parameters:
1338  * @ctx must point to an previously initialized `nk_context` struct
1339  * Return values:
1340  * returns 1 if any window is hovered or 0 otherwise */
1342 /* nk_item_is_any_active - returns if the any window is being hovered or any widget is currently active.
1343  * Can be used to decide if input should be processed by UI or your specific input handling.
1344  * Example could be UI and 3D camera to move inside a 3D space.
1345  * Parameters:
1346  * @ctx must point to an previously initialized `nk_context` struct
1347  * Return values:
1348  * returns 1 if any window is hovered or any item is active or 0 otherwise */
1350 /* nk_window_set_bounds - updates position and size of the currently processed window
1351  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1352  * Parameters:
1353  * @ctx must point to an previously initialized `nk_context` struct
1354  * @bounds points to a `nk_rect` struct with the new position and size of currently active window */
1355 NK_API void nk_window_set_bounds(struct nk_context*, struct nk_rect bounds);
1356 /* nk_window_set_position - updates position of the currently processed window
1357  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1358  * Parameters:
1359  * @ctx must point to an previously initialized `nk_context` struct
1360  * @pos points to a `nk_vec2` struct with the new position of currently active window */
1361 NK_API void nk_window_set_position(struct nk_context*, struct nk_vec2 pos);
1362 /* nk_window_set_size - updates size of the currently processed window
1363  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1364  * Parameters:
1365  * @ctx must point to an previously initialized `nk_context` struct
1366  * @bounds points to a `nk_vec2` struct with the new size of currently active window */
1367 NK_API void nk_window_set_size(struct nk_context*, struct nk_vec2);
1368 /* nk_window_set_focus - sets the window with given name as active
1369  * Parameters:
1370  * @ctx must point to an previously initialized `nk_context` struct
1371  * @name of the window to be set active */
1372 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1373 /* nk_window_close - closed a window and marks it for being freed at the end of the frame
1374  * Parameters:
1375  * @ctx must point to an previously initialized `nk_context` struct
1376  * @name of the window to be closed */
1377 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1378 /* nk_window_collapse - updates collapse state of a window with given name
1379  * Parameters:
1380  * @ctx must point to an previously initialized `nk_context` struct
1381  * @name of the window to be either collapse or maximize */
1382 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1383 /* nk_window_collapse - updates collapse state of a window with given name if given condition is met
1384  * Parameters:
1385  * @ctx must point to an previously initialized `nk_context` struct
1386  * @name of the window to be either collapse or maximize
1387  * @state the window should be put into
1388  * @condition that has to be true to actually commit the collapse state change */
1389 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1390 /* nk_window_show - updates visibility state of a window with given name
1391  * Parameters:
1392  * @ctx must point to an previously initialized `nk_context` struct
1393  * @name of the window to be either collapse or maximize
1394  * @state with either visible or hidden to modify the window with */
1395 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1396 /* nk_window_show_if - updates visibility state of a window with given name if a given condition is met
1397  * Parameters:
1398  * @ctx must point to an previously initialized `nk_context` struct
1399  * @name of the window to be either collapse or maximize
1400  * @state with either visible or hidden to modify the window with
1401  * @condition that has to be true to actually commit the visible state change */
1402 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1403 /* =============================================================================
1404  *
1405  * LAYOUT
1406  *
1407  * ============================================================================= */
1408 /* Layouting in general describes placing widget inside a window with position and size.
1409  * While in this particular implementation there are five different APIs for layouting
1410  * each with different trade offs between control and ease of use.
1411  *
1412  * All layouting methods in this library are based around the concept of a row.
1413  * A row has a height the window content grows by and a number of columns and each
1414  * layouting method specifies how each widget is placed inside the row.
1415  * After a row has been allocated by calling a layouting functions and then
1416  * filled with widgets will advance an internal pointer over the allocated row.
1417  *
1418  * To actually define a layout you just call the appropriate layouting function
1419  * and each subsequent widget call will place the widget as specified. Important
1420  * here is that if you define more widgets then columns defined inside the layout
1421  * functions it will allocate the next row without you having to make another layouting
1422  * call.
1423  *
1424  * Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
1425  * is that you have to define the row height for each. However the row height
1426  * often depends on the height of the font.
1427  *
1428  * To fix that internally nuklear uses a minimum row height that is set to the
1429  * height plus padding of currently active font and overwrites the row height
1430  * value if zero.
1431  *
1432  * If you manually want to change the minimum row height then
1433  * use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
1434  * reset it back to be derived from font height.
1435  *
1436  * Also if you change the font in nuklear it will automatically change the minimum
1437  * row height for you and. This means if you change the font but still want
1438  * a minimum row height smaller than the font you have to repush your value.
1439  *
1440  * For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
1441  * layouting method in combination with a cassowary constraint solver (there are
1442  * some versions on github with permissive license model) to take over all control over widget
1443  * layouting yourself. However for quick and dirty layouting using all the other layouting
1444  * functions should be fine.
1445  *
1446  * Usage
1447  * -------------------
1448  * 1.) nk_layout_row_dynamic
1449  * The easiest layouting function is `nk_layout_row_dynamic`. It provides each
1450  * widgets with same horizontal space inside the row and dynamically grows
1451  * if the owning window grows in width. So the number of columns dictates
1452  * the size of each widget dynamically by formula:
1453  *
1454  * widget_width = (window_width - padding - spacing) * (1/colum_count)
1455  *
1456  * Just like all other layouting APIs if you define more widget than columns this
1457  * library will allocate a new row and keep all layouting parameters previously
1458  * defined.
1459  *
1460  * if (nk_begin_xxx(...) {
1461  * // first row with height: 30 composed of two widgets
1462  * nk_layout_row_dynamic(&ctx, 30, 2);
1463  * nk_widget(...);
1464  * nk_widget(...);
1465  *
1466  * // second row with same parameter as defined above
1467  * nk_widget(...);
1468  * nk_widget(...);
1469  *
1470  * // third row uses 0 for height which will use auto layouting
1471  * nk_layout_row_dynamic(&ctx, 0, 2);
1472  * nk_widget(...);
1473  * nk_widget(...);
1474  * }
1475  * nk_end(...);
1476  *
1477  * 2.) nk_layout_row_static
1478  * Another easy layouting function is `nk_layout_row_static`. It provides each
1479  * widget with same horizontal pixel width inside the row and does not grow
1480  * if the owning window scales smaller or bigger.
1481  *
1482  * if (nk_begin_xxx(...) {
1483  * // first row with height: 30 composed of two widgets with width: 80
1484  * nk_layout_row_static(&ctx, 30, 80, 2);
1485  * nk_widget(...);
1486  * nk_widget(...);
1487  *
1488  * // second row with same parameter as defined above
1489  * nk_widget(...);
1490  * nk_widget(...);
1491  *
1492  * // third row uses 0 for height which will use auto layouting
1493  * nk_layout_row_static(&ctx, 0, 80, 2);
1494  * nk_widget(...);
1495  * nk_widget(...);
1496  * }
1497  * nk_end(...);
1498  *
1499  * 3.) nk_layout_row_xxx
1500  * A little bit more advanced layouting API are functions `nk_layout_row_begin`,
1501  * `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
1502  * specify each column pixel or window ratio in a row. It supports either
1503  * directly setting per column pixel width or widget window ratio but not
1504  * both. Furthermore it is a immediate mode API so each value is directly
1505  * pushed before calling a widget. Therefore the layout is not automatically
1506  * repeating like the last two layouting functions.
1507  *
1508  * if (nk_begin_xxx(...) {
1509  * // first row with height: 25 composed of two widgets with width 60 and 40
1510  * nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
1511  * nk_layout_row_push(ctx, 60);
1512  * nk_widget(...);
1513  * nk_layout_row_push(ctx, 40);
1514  * nk_widget(...);
1515  * nk_layout_row_end(ctx);
1516  *
1517  * // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
1518  * nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
1519  * nk_layout_row_push(ctx, 0.25f);
1520  * nk_widget(...);
1521  * nk_layout_row_push(ctx, 0.75f);
1522  * nk_widget(...);
1523  * nk_layout_row_end(ctx);
1524  *
1525  * // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
1526  * nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
1527  * nk_layout_row_push(ctx, 0.25f);
1528  * nk_widget(...);
1529  * nk_layout_row_push(ctx, 0.75f);
1530  * nk_widget(...);
1531  * nk_layout_row_end(ctx);
1532  * }
1533  * nk_end(...);
1534  *
1535  * 4.) nk_layout_row
1536  * The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
1537  * functions. Instead of pushing either pixel or window ratio for every widget
1538  * it allows to define it by array. The trade of for less control is that
1539  * `nk_layout_row` is automatically repeating. Otherwise the behavior is the
1540  * same.
1541  *
1542  * if (nk_begin_xxx(...) {
1543  * // two rows with height: 30 composed of two widgets with width 60 and 40
1544  * const float size[] = {60,40};
1545  * nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
1546  * nk_widget(...);
1547  * nk_widget(...);
1548  * nk_widget(...);
1549  * nk_widget(...);
1550  *
1551  * // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
1552  * const float ratio[] = {0.25, 0.75};
1553  * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1554  * nk_widget(...);
1555  * nk_widget(...);
1556  * nk_widget(...);
1557  * nk_widget(...);
1558  *
1559  * // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
1560  * const float ratio[] = {0.25, 0.75};
1561  * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1562  * nk_widget(...);
1563  * nk_widget(...);
1564  * nk_widget(...);
1565  * nk_widget(...);
1566  * }
1567  * nk_end(...);
1568  *
1569  * 5.) nk_layout_row_template_xxx
1570  * The most complex and second most flexible API is a simplified flexbox version without
1571  * line wrapping and weights for dynamic widgets. It is an immediate mode API but
1572  * unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
1573  * before calling the templated widgets.
1574  * The row template layout has three different per widget size specifier. The first
1575  * one is the static widget size specifier with fixed widget pixel width. They do
1576  * not grow if the row grows and will always stay the same. The second size
1577  * specifier is nk_layout_row_template_push_variable which defines a
1578  * minimum widget size but it also can grow if more space is available not taken
1579  * by other widgets. Finally there are dynamic widgets which are completely flexible
1580  * and unlike variable widgets can even shrink to zero if not enough space
1581  * is provided.
1582  *
1583  * if (nk_begin_xxx(...) {
1584  * // two rows with height: 30 composed of three widgets
1585  * nk_layout_row_template_begin(ctx, 30);
1586  * nk_layout_row_template_push_dynamic(ctx);
1587  * nk_layout_row_template_push_variable(ctx, 80);
1588  * nk_layout_row_template_push_static(ctx, 80);
1589  * nk_layout_row_template_end(ctx);
1590  *
1591  * nk_widget(...); // dynamic widget can go to zero if not enough space
1592  * nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
1593  * nk_widget(...); // static widget with fixed 80 pixel width
1594  *
1595  * // second row same layout
1596  * nk_widget(...);
1597  * nk_widget(...);
1598  * nk_widget(...);
1599  * }
1600  * nk_end(...);
1601  *
1602  * 6.) nk_layout_space_xxx
1603  * Finally the most flexible API directly allows you to place widgets inside the
1604  * window. The space layout API is an immediate mode API which does not support
1605  * row auto repeat and directly sets position and size of a widget. Position
1606  * and size hereby can be either specified as ratio of allocated space or
1607  * allocated space local position and pixel size. Since this API is quite
1608  * powerful there are a number of utility functions to get the available space
1609  * and convert between local allocated space and screen space.
1610  *
1611  * if (nk_begin_xxx(...) {
1612  * // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1613  * nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
1614  * nk_layout_space_push(ctx, nk_rect(0,0,150,200));
1615  * nk_widget(...);
1616  * nk_layout_space_push(ctx, nk_rect(200,200,100,200));
1617  * nk_widget(...);
1618  * nk_layout_space_end(ctx);
1619  *
1620  * // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1621  * nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
1622  * nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
1623  * nk_widget(...);
1624  * nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
1625  * nk_widget(...);
1626  * }
1627  * nk_end(...);
1628  *
1629  * Reference
1630  * -------------------
1631  * nk_layout_set_min_row_height - set the currently used minimum row height to a specified value
1632  * nk_layout_reset_min_row_height - resets the currently used minimum row height to font height
1633  *
1634  * nk_layout_widget_bounds - calculates current width a static layout row can fit inside a window
1635  * nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size
1636  *
1637  * nk_layout_row_dynamic - current layout is divided into n same sized growing columns
1638  * nk_layout_row_static - current layout is divided into n same fixed sized columns
1639  * nk_layout_row_begin - starts a new row with given height and number of columns
1640  * nk_layout_row_push - pushes another column with given size or window ratio
1641  * nk_layout_row_end - finished previously started row
1642  * nk_layout_row - specifies row columns in array as either window ratio or size
1643  *
1644  * nk_layout_row_template_begin - begins the row template declaration
1645  * nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space
1646  * nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width
1647  * nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size
1648  * nk_layout_row_template_end - marks the end of the row template
1649  *
1650  * nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size
1651  * nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio
1652  * nk_layout_space_end - marks the end of the layouting space
1653  *
1654  * nk_layout_space_bounds - callable after nk_layout_space_begin and returns total space allocated
1655  * nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space
1656  * nk_layout_space_to_local - converts vector from screen space into nk_layout_space coordinates
1657  * nk_layout_space_rect_to_screen - converts rectangle from nk_layout_space coordinate space into screen space
1658  * nk_layout_space_rect_to_local - converts rectangle from screen space into nk_layout_space coordinates
1659  */
1660 /* nk_layout_set_min_row_height - sets the currently used minimum row height.
1661  * IMPORTANT: The passed height needs to include both your preferred row height
1662  * as well as padding. No internal padding is added.
1663  * Parameters:
1664  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1665  * @height new minimum row height to be used for auto generating the row height */
1666 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height);
1667 /* nk_layout_reset_min_row_height - Reset the currently used minimum row height
1668  * back to font height + text padding + additional padding (style_window.min_row_height_padding)
1669  * Parameters:
1670  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` */
1672 /* nk_layout_widget_bounds - returns the width of the next row allocate by one of the layouting functions
1673  * Parameters:
1674  * @ctx must point to an previously initialized `nk_context` */
1676 /* nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size
1677  * Parameters:
1678  * @ctx must point to an previously initialized `nk_context`
1679  * @pixel_width to convert to window ratio */
1680 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
1681 /* nk_layout_row_dynamic - Sets current row layout to share horizontal space
1682  * between @cols number of widgets evenly. Once called all subsequent widget
1683  * calls greater than @cols will allocate a new row with same layout.
1684  * Parameters:
1685  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1686  * @row_height holds height of each widget in row or zero for auto layouting
1687  * @cols number of widget inside row */
1688 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
1689 /* nk_layout_row_static - Sets current row layout to fill @cols number of widgets
1690  * in row with same @item_width horizontal size. Once called all subsequent widget
1691  * calls greater than @cols will allocate a new row with same layout.
1692  * Parameters:
1693  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1694  * @height holds row height to allocate from panel for widget height
1695  * @item_width holds width of each widget in row
1696  * @cols number of widget inside row */
1697 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
1698 /* nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns.
1699  * Parameters:
1700  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1701  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1702  * @row_height holds height of each widget in row or zero for auto layouting
1703  * @cols number of widget inside row */
1704 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
1705 /* nk_layout_row_push - Specifies either window ratio or width of a single column
1706  * Parameters:
1707  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin`
1708  * @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */
1709 NK_API void nk_layout_row_push(struct nk_context*, float value);
1710 /* nk_layout_row_end - finished previously started row
1711  * Parameters:
1712  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin` */
1713 NK_API void nk_layout_row_end(struct nk_context*);
1714 /* nk_layout_row - specifies row columns in array as either window ratio or size
1715  * Parameters:
1716  * @ctx must point to an previously initialized `nk_context`
1717  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1718  * @row_height holds height of each widget in row or zero for auto layouting
1719  * @cols number of widget inside row */
1720 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
1721 /* nk_layout_row_template_begin - Begins the row template declaration
1722  * Parameters:
1723  * @ctx must point to an previously initialized `nk_context` struct
1724  * @row_height holds height of each widget in row or zero for auto layouting */
1725 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
1726 /* nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space
1727  * Parameters:
1728  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */
1730 /* nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width
1731  * Parameters:
1732  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin`
1733  * @min_width holds the minimum pixel width the next column must be */
1734 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
1735 /* nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size
1736  * Parameters:
1737  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin`
1738  * @width holds the absolute pixel width value the next column must be */
1739 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width);
1740 /* nk_layout_row_template_end - marks the end of the row template
1741  * Parameters:
1742  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */
1744 /* nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size.
1745  * Parameters:
1746  * @ctx must point to an previously initialized `nk_context` struct
1747  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1748  * @row_height holds height of each widget in row or zero for auto layouting
1749  * @widget_count number of widgets inside row */
1750 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
1751 /* nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio
1752  * Parameters:
1753  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1754  * @bounds position and size in laoyut space local coordinates */
1755 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect);
1756 /* nk_layout_space_end - marks the end of the layout space
1757  * Parameters:
1758  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */
1759 NK_API void nk_layout_space_end(struct nk_context*);
1760 /* nk_layout_space_bounds - returns total space allocated for `nk_layout_space`
1761  * Parameters:
1762  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */
1764 /* nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space
1765  * Parameters:
1766  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1767  * @vec position to convert from layout space into screen coordinate space */
1769 /* nk_layout_space_to_screen - converts vector from layout space into screen space
1770  * Parameters:
1771  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1772  * @vec position to convert from screen space into layout coordinate space */
1773 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
1774 /* nk_layout_space_rect_to_screen - converts rectangle from screen space into layout space
1775  * Parameters:
1776  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1777  * @bounds rectangle to convert from layout space into screen space */
1779 /* nk_layout_space_rect_to_local - converts rectangle from layout space into screen space
1780  * Parameters:
1781  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1782  * @bounds rectangle to convert from screen space into layout space */
1784 /* =============================================================================
1785  *
1786  * GROUP
1787  *
1788  * ============================================================================= */
1789 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
1790 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags);
1791 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags);
1793 NK_API void nk_group_end(struct nk_context*);
1794 /* =============================================================================
1795  *
1796  * LIST VIEW
1797  *
1798  * ============================================================================= */
1800 /* public: */
1801  int begin, end, count;
1802 /* private: */
1804  struct nk_context *ctx;
1805  nk_uint *scroll_pointer;
1806  nk_uint scroll_value;
1807 };
1808 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
1809 NK_API void nk_list_view_end(struct nk_list_view*);
1810 /* =============================================================================
1811  *
1812  * TREE
1813  *
1814  * ============================================================================= */
1815 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1816 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1817 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1818 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1819 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1820 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1821 NK_API void nk_tree_pop(struct nk_context*);
1822 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
1823 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
1824 NK_API void nk_tree_state_pop(struct nk_context*);
1825 /* =============================================================================
1826  *
1827  * WIDGET
1828  *
1829  * ============================================================================= */
1831  NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
1832  NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
1833  NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
1834 };
1837  NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */
1838  NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */
1839  NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */
1840  NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */
1841  NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
1844 };
1845 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
1847 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
1849 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
1850 NK_API float nk_widget_width(struct nk_context*);
1851 NK_API float nk_widget_height(struct nk_context*);
1854 NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down);
1855 NK_API void nk_spacing(struct nk_context*, int cols);
1856 /* =============================================================================
1857  *
1858  * TEXT
1859  *
1860  * ============================================================================= */
1868 };
1873 };
1874 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
1875 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
1876 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
1877 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
1878 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
1879 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
1880 NK_API void nk_label_wrap(struct nk_context*, const char*);
1881 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
1882 NK_API void nk_image(struct nk_context*, struct nk_image);
1883 #ifdef NK_INCLUDE_STANDARD_VARARGS
1884 NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...);
1885 NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...);
1886 NK_API void nk_labelf_wrap(struct nk_context*, const char*,...);
1887 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...);
1888 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
1889 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
1890 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
1891 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
1892 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
1893 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
1894 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
1895 #endif
1896 /* =============================================================================
1897  *
1898  * BUTTON
1899  *
1900  * ============================================================================= */
1901 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
1902 NK_API int nk_button_label(struct nk_context*, const char *title);
1903 NK_API int nk_button_color(struct nk_context*, struct nk_color);
1905 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
1906 NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment);
1907 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1908 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
1909 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
1910 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
1911 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
1912 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
1913 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
1914 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1915 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
1916 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
1917 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
1921 /* =============================================================================
1922  *
1923  * CHECKBOX
1924  *
1925  * ============================================================================= */
1926 NK_API int nk_check_label(struct nk_context*, const char*, int active);
1927 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
1928 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
1929 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
1930 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
1931 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
1932 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
1933 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
1934 /* =============================================================================
1935  *
1936  * RADIO BUTTON
1937  *
1938  * ============================================================================= */
1939 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
1940 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
1941 NK_API int nk_option_label(struct nk_context*, const char*, int active);
1942 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
1943 /* =============================================================================
1944  *
1945  * SELECTABLE
1946  *
1947  * ============================================================================= */
1948 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
1949 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
1950 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value);
1951 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
1952 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
1953 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
1954 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
1955 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
1956 /* =============================================================================
1957  *
1958  * SLIDER
1959  *
1960  * ============================================================================= */
1961 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
1962 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
1963 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
1964 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
1965 /* =============================================================================
1966  *
1967  * PROGRESSBAR
1968  *
1969  * ============================================================================= */
1970 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
1971 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
1972 
1973 /* =============================================================================
1974  *
1975  * COLOR PICKER
1976  *
1977  * ============================================================================= */
1978 NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format);
1979 NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format);
1980 /* =============================================================================
1981  *
1982  * PROPERTIES
1983  *
1984  * ============================================================================= */
1985 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
1986 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
1987 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
1988 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
1989 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
1990 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
1991 /* =============================================================================
1992  *
1993  * TEXT EDIT
1994  *
1995  * ============================================================================= */
2010 };
2016 };
2018  NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */
2019  NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */
2020  NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */
2021  NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
2022  NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */
2023 };
2024 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
2025 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter);
2026 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter);
2027 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags);
2028 NK_API void nk_edit_unfocus(struct nk_context*);
2029 /* =============================================================================
2030  *
2031  * CHART
2032  *
2033  * ============================================================================= */
2034 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
2035 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
2036 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
2037 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
2038 NK_API nk_flags nk_chart_push(struct nk_context*, float);
2039 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
2040 NK_API void nk_chart_end(struct nk_context*);
2041 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
2042 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
2043 /* =============================================================================
2044  *
2045  * POPUP
2046  *
2047  * ============================================================================= */
2048 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
2049 NK_API void nk_popup_close(struct nk_context*);
2050 NK_API void nk_popup_end(struct nk_context*);
2051 /* =============================================================================
2052  *
2053  * COMBOBOX
2054  *
2055  * ============================================================================= */
2056 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
2057 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
2058 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
2059 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
2060 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
2061 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
2062 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size);
2063 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
2064 /* =============================================================================
2065  *
2066  * ABSTRACT COMBOBOX
2067  *
2068  * ============================================================================= */
2069 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
2070 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
2071 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
2072 NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size);
2073 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
2074 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
2075 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
2076 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
2077 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
2078 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
2079 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
2080 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2081 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
2082 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2083 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2084 NK_API void nk_combo_close(struct nk_context*);
2085 NK_API void nk_combo_end(struct nk_context*);
2086 /* =============================================================================
2087  *
2088  * CONTEXTUAL
2089  *
2090  * ============================================================================= */
2091 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
2092 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
2093 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
2094 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2095 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2096 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2097 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2098 NK_API void nk_contextual_close(struct nk_context*);
2099 NK_API void nk_contextual_end(struct nk_context*);
2100 /* =============================================================================
2101  *
2102  * TOOLTIP
2103  *
2104  * ============================================================================= */
2105 NK_API void nk_tooltip(struct nk_context*, const char*);
2106 NK_API int nk_tooltip_begin(struct nk_context*, float width);
2107 NK_API void nk_tooltip_end(struct nk_context*);
2108 /* =============================================================================
2109  *
2110  * MENU
2111  *
2112  * ============================================================================= */
2113 NK_API void nk_menubar_begin(struct nk_context*);
2114 NK_API void nk_menubar_end(struct nk_context*);
2115 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
2116 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
2117 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
2118 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
2119 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
2120 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
2121 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2122 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2123 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
2124 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
2125 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2126 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2127 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2128 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2129 NK_API void nk_menu_close(struct nk_context*);
2130 NK_API void nk_menu_end(struct nk_context*);
2131 /* =============================================================================
2132  *
2133  * STYLE
2134  *
2135  * ============================================================================= */
2166 };
2176 };
2177 NK_API void nk_style_default(struct nk_context*);
2178 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
2179 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
2180 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
2182 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
2184 NK_API void nk_style_show_cursor(struct nk_context*);
2185 NK_API void nk_style_hide_cursor(struct nk_context*);
2186 
2187 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
2188 NK_API int nk_style_push_float(struct nk_context*, float*, float);
2189 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
2191 NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags);
2192 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
2193 
2194 NK_API int nk_style_pop_font(struct nk_context*);
2195 NK_API int nk_style_pop_float(struct nk_context*);
2196 NK_API int nk_style_pop_vec2(struct nk_context*);
2198 NK_API int nk_style_pop_flags(struct nk_context*);
2199 NK_API int nk_style_pop_color(struct nk_context*);
2200 /* =============================================================================
2201  *
2202  * COLOR
2203  *
2204  * ============================================================================= */
2205 NK_API struct nk_color nk_rgb(int r, int g, int b);
2206 NK_API struct nk_color nk_rgb_iv(const int *rgb);
2207 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
2208 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
2209 NK_API struct nk_color nk_rgb_fv(const float *rgb);
2210 NK_API struct nk_color nk_rgb_hex(const char *rgb);
2211 
2212 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
2213 NK_API struct nk_color nk_rgba_u32(nk_uint);
2214 NK_API struct nk_color nk_rgba_iv(const int *rgba);
2215 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
2216 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
2217 NK_API struct nk_color nk_rgba_fv(const float *rgba);
2218 NK_API struct nk_color nk_rgba_hex(const char *rgb);
2219 
2220 NK_API struct nk_color nk_hsv(int h, int s, int v);
2221 NK_API struct nk_color nk_hsv_iv(const int *hsv);
2222 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
2223 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
2224 NK_API struct nk_color nk_hsv_fv(const float *hsv);
2225 
2226 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
2227 NK_API struct nk_color nk_hsva_iv(const int *hsva);
2228 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
2229 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
2230 NK_API struct nk_color nk_hsva_fv(const float *hsva);
2231 
2232 /* color (conversion nuklear --> user) */
2233 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
2234 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
2235 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
2236 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
2237 
2238 NK_API nk_uint nk_color_u32(struct nk_color);
2239 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
2240 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
2241 
2242 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
2243 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
2244 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
2245 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
2246 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
2247 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
2248 
2249 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
2250 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color);
2251 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
2252 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
2253 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
2254 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
2255 /* =============================================================================
2256  *
2257  * IMAGE
2258  *
2259  * ============================================================================= */
2260 NK_API nk_handle nk_handle_ptr(void*);
2261 NK_API nk_handle nk_handle_id(int);
2262 NK_API struct nk_image nk_image_handle(nk_handle);
2263 NK_API struct nk_image nk_image_ptr(void*);
2264 NK_API struct nk_image nk_image_id(int);
2265 NK_API int nk_image_is_subimage(const struct nk_image* img);
2266 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
2267 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
2268 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
2269 /* =============================================================================
2270  *
2271  * MATH
2272  *
2273  * ============================================================================= */
2274 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
2275 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
2276 
2277 NK_API struct nk_vec2 nk_vec2(float x, float y);
2278 NK_API struct nk_vec2 nk_vec2i(int x, int y);
2279 NK_API struct nk_vec2 nk_vec2v(const float *xy);
2280 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
2281 
2283 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
2284 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
2285 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
2286 NK_API struct nk_rect nk_rectv(const float *xywh);
2287 NK_API struct nk_rect nk_rectiv(const int *xywh);
2288 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
2289 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
2290 /* =============================================================================
2291  *
2292  * STRING
2293  *
2294  * ============================================================================= */
2295 NK_API int nk_strlen(const char *str);
2296 NK_API int nk_stricmp(const char *s1, const char *s2);
2297 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
2298 NK_API int nk_strtoi(const char *str, const char **endptr);
2299 NK_API float nk_strtof(const char *str, const char **endptr);
2300 NK_API double nk_strtod(const char *str, const char **endptr);
2301 NK_API int nk_strfilter(const char *text, const char *regexp);
2302 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
2303 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
2304 /* =============================================================================
2305  *
2306  * UTF-8
2307  *
2308  * ============================================================================= */
2309 NK_API int nk_utf_decode(const char*, nk_rune*, int);
2310 NK_API int nk_utf_encode(nk_rune, char*, int);
2311 NK_API int nk_utf_len(const char*, int byte_len);
2312 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
2313 /* ===============================================================
2314  *
2315  * FONT
2316  *
2317  * ===============================================================*/
2318 /* Font handling in this library was designed to be quite customizable and lets
2319  you decide what you want to use and what you want to provide. There are three
2320  different ways to use the font atlas. The first two will use your font
2321  handling scheme and only requires essential data to run nuklear. The next
2322  slightly more advanced features is font handling with vertex buffer output.
2323  Finally the most complex API wise is using nuklear's font baking API.
2324 
2325  1.) Using your own implementation without vertex buffer output
2326  --------------------------------------------------------------
2327  So first up the easiest way to do font handling is by just providing a
2328  `nk_user_font` struct which only requires the height in pixel of the used
2329  font and a callback to calculate the width of a string. This way of handling
2330  fonts is best fitted for using the normal draw shape command API where you
2331  do all the text drawing yourself and the library does not require any kind
2332  of deeper knowledge about which font handling mechanism you use.
2333  IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
2334  over the complete life time! I know this sucks but it is currently the only
2335  way to switch between fonts.
2336 
2337  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2338  {
2339  your_font_type *type = handle.ptr;
2340  float text_width = ...;
2341  return text_width;
2342  }
2343 
2344  struct nk_user_font font;
2345  font.userdata.ptr = &your_font_class_or_struct;
2346  font.height = your_font_height;
2347  font.width = your_text_width_calculation;
2348 
2349  struct nk_context ctx;
2350  nk_init_default(&ctx, &font);
2351 
2352  2.) Using your own implementation with vertex buffer output
2353  --------------------------------------------------------------
2354  While the first approach works fine if you don't want to use the optional
2355  vertex buffer output it is not enough if you do. To get font handling working
2356  for these cases you have to provide two additional parameters inside the
2357  `nk_user_font`. First a texture atlas handle used to draw text as subimages
2358  of a bigger font atlas texture and a callback to query a character's glyph
2359  information (offset, size, ...). So it is still possible to provide your own
2360  font and use the vertex buffer output.
2361 
2362  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2363  {
2364  your_font_type *type = handle.ptr;
2365  float text_width = ...;
2366  return text_width;
2367  }
2368  void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
2369  {
2370  your_font_type *type = handle.ptr;
2371  glyph.width = ...;
2372  glyph.height = ...;
2373  glyph.xadvance = ...;
2374  glyph.uv[0].x = ...;
2375  glyph.uv[0].y = ...;
2376  glyph.uv[1].x = ...;
2377  glyph.uv[1].y = ...;
2378  glyph.offset.x = ...;
2379  glyph.offset.y = ...;
2380  }
2381 
2382  struct nk_user_font font;
2383  font.userdata.ptr = &your_font_class_or_struct;
2384  font.height = your_font_height;
2385  font.width = your_text_width_calculation;
2386  font.query = query_your_font_glyph;
2387  font.texture.id = your_font_texture;
2388 
2389  struct nk_context ctx;
2390  nk_init_default(&ctx, &font);
2391 
2392  3.) Nuklear font baker
2393  ------------------------------------
2394  The final approach if you do not have a font handling functionality or don't
2395  want to use it in this library is by using the optional font baker.
2396  The font baker APIs can be used to create a font plus font atlas texture
2397  and can be used with or without the vertex buffer output.
2398 
2399  It still uses the `nk_user_font` struct and the two different approaches
2400  previously stated still work. The font baker is not located inside
2401  `nk_context` like all other systems since it can be understood as more of
2402  an extension to nuklear and does not really depend on any `nk_context` state.
2403 
2404  Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
2405  functions. If you don't care about memory just call the default version
2406  `nk_font_atlas_init_default` which will allocate all memory from the standard library.
2407  If you want to control memory allocation but you don't care if the allocated
2408  memory is temporary and therefore can be freed directly after the baking process
2409  is over or permanent you can call `nk_font_atlas_init`.
2410 
2411  After successfully initializing the font baker you can add Truetype(.ttf) fonts from
2412  different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
2413  functions. Adding font will permanently store each font, font config and ttf memory block(!)
2414  inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
2415  the font baker by for example adding additional fonts you can call
2416  `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
2417 
2418  As soon as you added all fonts you wanted you can now start the baking process
2419  for every selected glyph to image by calling `nk_font_atlas_bake`.
2420  The baking process returns image memory, width and height which can be used to
2421  either create your own image object or upload it to any graphics library.
2422  No matter which case you finally have to call `nk_font_atlas_end` which
2423  will free all temporary memory including the font atlas image so make sure
2424  you created our texture beforehand. `nk_font_atlas_end` requires a handle
2425  to your font texture or object and optionally fills a `struct nk_draw_null_texture`
2426  which can be used for the optional vertex output. If you don't want it just
2427  set the argument to `NULL`.
2428 
2429  At this point you are done and if you don't want to reuse the font atlas you
2430  can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
2431  memory. Finally if you don't use the font atlas and any of it's fonts anymore
2432  you need to call `nk_font_atlas_clear` to free all memory still being used.
2433 
2434  struct nk_font_atlas atlas;
2435  nk_font_atlas_init_default(&atlas);
2436  nk_font_atlas_begin(&atlas);
2437  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
2438  nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
2439  const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
2440  nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
2441 
2442  struct nk_context ctx;
2443  nk_init_default(&ctx, &font->handle);
2444  while (1) {
2445 
2446  }
2447  nk_font_atlas_clear(&atlas);
2448 
2449  The font baker API is probably the most complex API inside this library and
2450  I would suggest reading some of my examples `example/` to get a grip on how
2451  to use the font atlas. There are a number of details I left out. For example
2452  how to merge fonts, configure a font with `nk_font_config` to use other languages,
2453  use another texture coordinate format and a lot more:
2454 
2455  struct nk_font_config cfg = nk_font_config(font_pixel_height);
2456  cfg.merge_mode = nk_false or nk_true;
2457  cfg.range = nk_font_korean_glyph_ranges();
2458  cfg.coord_type = NK_COORD_PIXEL;
2459  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
2460 
2461 */
2462 struct nk_user_font_glyph;
2463 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
2464 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
2465  struct nk_user_font_glyph *glyph,
2466  nk_rune codepoint, nk_rune next_codepoint);
2467 
2468 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2469 struct nk_user_font_glyph {
2470  struct nk_vec2 uv[2];
2471  /* texture coordinates */
2472  struct nk_vec2 offset;
2473  /* offset between top left and glyph */
2474  float width, height;
2475  /* size of the glyph */
2476  float xadvance;
2477  /* offset to the next glyph */
2478 };
2479 #endif
2480 
2482  nk_handle userdata;
2483  /* user provided font handle */
2484  float height;
2485  /* max height of the font */
2487  /* font string width in pixel callback */
2488 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2489  nk_query_font_glyph_f query;
2490  /* font glyph callback to query drawing info */
2491  nk_handle texture;
2492  /* texture handle to the used font atlas or texture */
2493 #endif
2494 };
2495 
2496 #ifdef NK_INCLUDE_FONT_BAKING
2497 enum nk_font_coord_type {
2498  NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
2499  NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
2500 };
2501 
2502 struct nk_baked_font {
2503  float height;
2504  /* height of the font */
2505  float ascent, descent;
2506  /* font glyphs ascent and descent */
2507  nk_rune glyph_offset;
2508  /* glyph array offset inside the font glyph baking output array */
2509  nk_rune glyph_count;
2510  /* number of glyphs of this font inside the glyph baking array output */
2511  const nk_rune *ranges;
2512  /* font codepoint ranges as pairs of (from/to) and 0 as last element */
2513 };
2514 
2515 struct nk_font_config {
2516  struct nk_font_config *next;
2517  /* NOTE: only used internally */
2518  void *ttf_blob;
2519  /* pointer to loaded TTF file memory block.
2520  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2521  nk_size ttf_size;
2522  /* size of the loaded TTF file memory block
2523  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2524 
2525  unsigned char ttf_data_owned_by_atlas;
2526  /* used inside font atlas: default to: 0*/
2527  unsigned char merge_mode;
2528  /* merges this font into the last font */
2529  unsigned char pixel_snap;
2530  /* align every character to pixel boundary (if true set oversample (1,1)) */
2531  unsigned char oversample_v, oversample_h;
2532  /* rasterize at hight quality for sub-pixel position */
2533  unsigned char padding[3];
2534 
2535  float size;
2536  /* baked pixel height of the font */
2537  enum nk_font_coord_type coord_type;
2538  /* texture coordinate format with either pixel or UV coordinates */
2539  struct nk_vec2 spacing;
2540  /* extra pixel spacing between glyphs */
2541  const nk_rune *range;
2542  /* list of unicode ranges (2 values per range, zero terminated) */
2543  struct nk_baked_font *font;
2544  /* font to setup in the baking process: NOTE: not needed for font atlas */
2545  nk_rune fallback_glyph;
2546  /* fallback glyph to use if a given rune is not found */
2547 };
2548 
2549 struct nk_font_glyph {
2550  nk_rune codepoint;
2551  float xadvance;
2552  float x0, y0, x1, y1, w, h;
2553  float u0, v0, u1, v1;
2554 };
2555 
2556 struct nk_font {
2557  struct nk_font *next;
2558  struct nk_user_font handle;
2559  struct nk_baked_font info;
2560  float scale;
2561  struct nk_font_glyph *glyphs;
2562  const struct nk_font_glyph *fallback;
2563  nk_rune fallback_codepoint;
2564  nk_handle texture;
2565  struct nk_font_config *config;
2566 };
2567 
2568 enum nk_font_atlas_format {
2569  NK_FONT_ATLAS_ALPHA8,
2570  NK_FONT_ATLAS_RGBA32
2571 };
2572 
2573 struct nk_font_atlas {
2574  void *pixel;
2575  int tex_width;
2576  int tex_height;
2577 
2578  struct nk_allocator permanent;
2579  struct nk_allocator temporary;
2580 
2581  struct nk_recti custom;
2582  struct nk_cursor cursors[NK_CURSOR_COUNT];
2583 
2584  int glyph_count;
2585  struct nk_font_glyph *glyphs;
2586  struct nk_font *default_font;
2587  struct nk_font *fonts;
2588  struct nk_font_config *config;
2589  int font_num;
2590 };
2591 
2592 /* some language glyph codepoint ranges */
2593 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
2594 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
2595 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
2596 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
2597 
2598 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2599 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
2600 #endif
2601 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
2602 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
2603 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
2604 NK_API struct nk_font_config nk_font_config(float pixel_height);
2605 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
2606 #ifdef NK_INCLUDE_DEFAULT_FONT
2607 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
2608 #endif
2609 NK_API struct nk_font* nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, nk_size size, float height, const struct nk_font_config *config);
2610 #ifdef NK_INCLUDE_STANDARD_IO
2611 NK_API struct nk_font* nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, float height, const struct nk_font_config*);
2612 #endif
2613 NK_API struct nk_font *nk_font_atlas_add_compressed(struct nk_font_atlas*, void *memory, nk_size size, float height, const struct nk_font_config*);
2614 NK_API struct nk_font* nk_font_atlas_add_compressed_base85(struct nk_font_atlas*, const char *data, float height, const struct nk_font_config *config);
2615 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
2616 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
2617 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
2618 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
2619 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
2620 
2621 #endif
2622 
2623 /* ==============================================================
2624  *
2625  * MEMORY BUFFER
2626  *
2627  * ===============================================================*/
2628 /* A basic (double)-buffer with linear allocation and resetting as only
2629  freeing policy. The buffer's main purpose is to control all memory management
2630  inside the GUI toolkit and still leave memory control as much as possible in
2631  the hand of the user while also making sure the library is easy to use if
2632  not as much control is needed.
2633  In general all memory inside this library can be provided from the user in
2634  three different ways.
2635 
2636  The first way and the one providing most control is by just passing a fixed
2637  size memory block. In this case all control lies in the hand of the user
2638  since he can exactly control where the memory comes from and how much memory
2639  the library should consume. Of course using the fixed size API removes the
2640  ability to automatically resize a buffer if not enough memory is provided so
2641  you have to take over the resizing. While being a fixed sized buffer sounds
2642  quite limiting, it is very effective in this library since the actual memory
2643  consumption is quite stable and has a fixed upper bound for a lot of cases.
2644 
2645  If you don't want to think about how much memory the library should allocate
2646  at all time or have a very dynamic UI with unpredictable memory consumption
2647  habits but still want control over memory allocation you can use the dynamic
2648  allocator based API. The allocator consists of two callbacks for allocating
2649  and freeing memory and optional userdata so you can plugin your own allocator.
2650 
2651  The final and easiest way can be used by defining
2652  NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
2653  allocation functions malloc and free and takes over complete control over
2654  memory in this library.
2655 */
2657  void *memory;
2658  unsigned int type;
2659  nk_size size;
2660  nk_size allocated;
2661  nk_size needed;
2662  nk_size calls;
2663 };
2664 
2668 };
2669 
2674 };
2675 
2677  int active;
2678  nk_size offset;
2679 };
2680 
2681 struct nk_memory {void *ptr;nk_size size;};
2682 struct nk_buffer {
2684  /* buffer marker to free a buffer to a certain offset */
2686  /* allocator callback for dynamic buffers */
2688  /* memory management type */
2690  /* memory and size of the current memory block */
2692  /* growing factor for dynamic memory management */
2693  nk_size allocated;
2694  /* total amount of memory allocated */
2695  nk_size needed;
2696  /* totally consumed memory given that enough memory is present */
2697  nk_size calls;
2698  /* number of allocation calls */
2699  nk_size size;
2700  /* current size of the buffer */
2701 };
2702 
2703 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2704 NK_API void nk_buffer_init_default(struct nk_buffer*);
2705 #endif
2706 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
2707 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
2708 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
2709 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
2710 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type);
2712 NK_API void nk_buffer_clear(struct nk_buffer*);
2713 NK_API void nk_buffer_free(struct nk_buffer*);
2714 NK_API void *nk_buffer_memory(struct nk_buffer*);
2715 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
2716 NK_API nk_size nk_buffer_total(struct nk_buffer*);
2717 
2718 /* ==============================================================
2719  *
2720  * STRING
2721  *
2722  * ===============================================================*/
2723 /* Basic string buffer which is only used in context with the text editor
2724  * to manage and manipulate dynamic or fixed size string content. This is _NOT_
2725  * the default string handling method. The only instance you should have any contact
2726  * with this API is if you interact with an `nk_text_edit` object inside one of the
2727  * copy and paste functions and even there only for more advanced cases. */
2728 struct nk_str {
2730  int len; /* in codepoints/runes/glyphs */
2731 };
2732 
2733 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2734 NK_API void nk_str_init_default(struct nk_str*);
2735 #endif
2736 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
2737 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
2738 NK_API void nk_str_clear(struct nk_str*);
2739 NK_API void nk_str_free(struct nk_str*);
2740 
2741 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
2742 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
2743 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
2744 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
2745 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
2746 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
2747 
2748 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
2749 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
2750 
2751 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
2752 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
2753 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
2754 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
2755 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
2756 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
2757 
2758 NK_API void nk_str_remove_chars(struct nk_str*, int len);
2759 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
2760 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
2761 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
2762 
2763 NK_API char *nk_str_at_char(struct nk_str*, int pos);
2764 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
2765 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
2766 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
2767 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
2768 
2769 NK_API char *nk_str_get(struct nk_str*);
2770 NK_API const char *nk_str_get_const(const struct nk_str*);
2771 NK_API int nk_str_len(struct nk_str*);
2772 NK_API int nk_str_len_char(struct nk_str*);
2773 
2774 /*===============================================================
2775  *
2776  * TEXT EDITOR
2777  *
2778  * ===============================================================*/
2779 /* Editing text in this library is handled by either `nk_edit_string` or
2780  * `nk_edit_buffer`. But like almost everything in this library there are multiple
2781  * ways of doing it and a balance between control and ease of use with memory
2782  * as well as functionality controlled by flags.
2783  *
2784  * This library generally allows three different levels of memory control:
2785  * First of is the most basic way of just providing a simple char array with
2786  * string length. This method is probably the easiest way of handling simple
2787  * user text input. Main upside is complete control over memory while the biggest
2788  * downside in comparison with the other two approaches is missing undo/redo.
2789  *
2790  * For UIs that require undo/redo the second way was created. It is based on
2791  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
2792  * This is mainly useful if you want something more like a text editor but don't want
2793  * to have a dynamically growing buffer.
2794  *
2795  * The final way is using a dynamically growing nk_text_edit struct, which
2796  * has both a default version if you don't care where memory comes from and an
2797  * allocator version if you do. While the text editor is quite powerful for its
2798  * complexity I would not recommend editing gigabytes of data with it.
2799  * It is rather designed for uses cases which make sense for a GUI library not for
2800  * an full blown text editor.
2801  */
2802 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
2803 #define NK_TEXTEDIT_UNDOSTATECOUNT 99
2804 #endif
2805 
2806 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
2807 #define NK_TEXTEDIT_UNDOCHARCOUNT 999
2808 #endif
2809 
2810 struct nk_text_edit;
2812  nk_handle userdata;
2815 };
2816 
2818  int where;
2822 };
2823 
2827  short undo_point;
2828  short redo_point;
2831 };
2832 
2836 };
2837 
2842 };
2843 
2846  struct nk_str string;
2849 
2850  int cursor;
2853  unsigned char mode;
2854  unsigned char cursor_at_end_of_line;
2855  unsigned char initialized;
2856  unsigned char has_preferred_x;
2857  unsigned char single_line;
2858  unsigned char active;
2859  unsigned char padding1;
2862 };
2863 
2864 /* filter function */
2865 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
2866 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
2867 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
2868 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
2869 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
2870 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
2871 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
2872 
2873 /* text editor */
2874 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2875 NK_API void nk_textedit_init_default(struct nk_text_edit*);
2876 #endif
2877 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size);
2878 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
2879 NK_API void nk_textedit_free(struct nk_text_edit*);
2880 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
2881 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
2884 NK_API int nk_textedit_cut(struct nk_text_edit*);
2885 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
2886 NK_API void nk_textedit_undo(struct nk_text_edit*);
2887 NK_API void nk_textedit_redo(struct nk_text_edit*);
2888 
2889 /* ===============================================================
2890  *
2891  * DRAWING
2892  *
2893  * ===============================================================*/
2894 /* This library was designed to be render backend agnostic so it does
2895  not draw anything to screen. Instead all drawn shapes, widgets
2896  are made of, are buffered into memory and make up a command queue.
2897  Each frame therefore fills the command buffer with draw commands
2898  that then need to be executed by the user and his own render backend.
2899  After that the command buffer needs to be cleared and a new frame can be
2900  started. It is probably important to note that the command buffer is the main
2901  drawing API and the optional vertex buffer API only takes this format and
2902  converts it into a hardware accessible format.
2903 
2904  To use the command queue to draw your own widgets you can access the
2905  command buffer of each window by calling `nk_window_get_canvas` after
2906  previously having called `nk_begin`:
2907 
2908  void draw_red_rectangle_widget(struct nk_context *ctx)
2909  {
2910  struct nk_command_buffer *canvas;
2911  struct nk_input *input = &ctx->input;
2912  canvas = nk_window_get_canvas(ctx);
2913 
2914  struct nk_rect space;
2915  enum nk_widget_layout_states state;
2916  state = nk_widget(&space, ctx);
2917  if (!state) return;
2918 
2919  if (state != NK_WIDGET_ROM)
2920  update_your_widget_by_user_input(...);
2921  nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
2922  }
2923 
2924  if (nk_begin(...)) {
2925  nk_layout_row_dynamic(ctx, 25, 1);
2926  draw_red_rectangle_widget(ctx);
2927  }
2928  nk_end(..)
2929 
2930  Important to know if you want to create your own widgets is the `nk_widget`
2931  call. It allocates space on the panel reserved for this widget to be used,
2932  but also returns the state of the widget space. If your widget is not seen and does
2933  not have to be updated it is '0' and you can just return. If it only has
2934  to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
2935  update and draw your widget. The reason for separating is to only draw and
2936  update what is actually necessary which is crucial for performance.
2937 */
2958 };
2959 
2960 /* command base and header of every command inside the buffer */
2961 struct nk_command {
2963  nk_size next;
2964 #ifdef NK_INCLUDE_COMMAND_USERDATA
2965  nk_handle userdata;
2966 #endif
2967 };
2968 
2971  short x, y;
2972  unsigned short w, h;
2973 };
2974 
2977  unsigned short line_thickness;
2978  struct nk_vec2i begin;
2979  struct nk_vec2i end;
2980  struct nk_color color;
2981 };
2982 
2985  unsigned short line_thickness;
2986  struct nk_vec2i begin;
2987  struct nk_vec2i end;
2988  struct nk_vec2i ctrl[2];
2989  struct nk_color color;
2990 };
2991 
2994  unsigned short rounding;
2995  unsigned short line_thickness;
2996  short x, y;
2997  unsigned short w, h;
2998  struct nk_color color;
2999 };
3000 
3003  unsigned short rounding;
3004  short x, y;
3005  unsigned short w, h;
3006  struct nk_color color;
3007 };
3008 
3011  short x, y;
3012  unsigned short w, h;
3013  struct nk_color left;
3014  struct nk_color top;
3016  struct nk_color right;
3017 };
3018 
3021  unsigned short line_thickness;
3022  struct nk_vec2i a;
3023  struct nk_vec2i b;
3024  struct nk_vec2i c;
3025  struct nk_color color;
3026 };
3027 
3030  struct nk_vec2i a;
3031  struct nk_vec2i b;
3032  struct nk_vec2i c;
3033  struct nk_color color;
3034 };
3035 
3038  short x, y;
3039  unsigned short line_thickness;
3040  unsigned short w, h;
3041  struct nk_color color;
3042 };
3043 
3046  short x, y;
3047  unsigned short w, h;
3048  struct nk_color color;
3049 };
3050 
3053  short cx, cy;
3054  unsigned short r;
3055  unsigned short line_thickness;
3056  float a[2];
3057  struct nk_color color;
3058 };
3059 
3062  short cx, cy;
3063  unsigned short r;
3064  float a[2];
3065  struct nk_color color;
3066 };
3067 
3070  struct nk_color color;
3071  unsigned short line_thickness;
3072  unsigned short point_count;
3073  struct nk_vec2i points[1];
3074 };
3075 
3078  struct nk_color color;
3079  unsigned short point_count;
3080  struct nk_vec2i points[1];
3081 };
3082 
3085  struct nk_color color;
3086  unsigned short line_thickness;
3087  unsigned short point_count;
3088  struct nk_vec2i points[1];
3089 };
3090 
3093  short x, y;
3094  unsigned short w, h;
3095  struct nk_image img;
3096  struct nk_color col;
3097 };
3098 
3099 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
3100  unsigned short w, unsigned short h, nk_handle callback_data);
3103  short x, y;
3104  unsigned short w, h;
3105  nk_handle callback_data;
3107 };
3108 
3111  const struct nk_user_font *font;
3114  short x, y;
3115  unsigned short w, h;
3116  float height;
3117  int length;
3118  char string[1];
3119 };
3120 
3124 };
3125 
3127  struct nk_buffer *base;
3128  struct nk_rect clip;
3130  nk_handle userdata;
3131  nk_size begin, end, last;
3132 };
3133 
3134 /* shape outlines */
3135 NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color);
3136 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
3137 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
3138 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
3139 NK_API void nk_stroke_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color);
3140 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
3141 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
3142 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
3143 
3144 /* filled shades */
3145 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
3146 NK_API void nk_fill_rect_multi_color(struct nk_command_buffer*, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
3147 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
3148 NK_API void nk_fill_arc(struct nk_command_buffer*, float cx, float cy, float radius, float a_min, float a_max, struct nk_color);
3149 NK_API void nk_fill_triangle(struct nk_command_buffer*, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color);
3150 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
3151 
3152 /* misc */
3153 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
3154 NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color);
3155 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
3156 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr);
3157 
3158 /* ===============================================================
3159  *
3160  * INPUT
3161  *
3162  * ===============================================================*/
3164  int down;
3165  unsigned int clicked;
3167 };
3168 struct nk_mouse {
3170  struct nk_vec2 pos;
3171  struct nk_vec2 prev;
3172  struct nk_vec2 delta;
3174  unsigned char grab;
3175  unsigned char grabbed;
3176  unsigned char ungrab;
3177 };
3178 
3179 struct nk_key {
3180  int down;
3181  unsigned int clicked;
3182 };
3183 struct nk_keyboard {
3187 };
3188 
3189 struct nk_input {
3191  struct nk_mouse mouse;
3192 };
3193 
3194 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
3195 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3196 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
3197 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3198 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
3199 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
3200 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
3201 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
3202 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
3203 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
3204 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
3205 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
3206 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
3207 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
3208 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
3209 
3210 /* ===============================================================
3211  *
3212  * DRAW LIST
3213  *
3214  * ===============================================================*/
3215 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3216 /* The optional vertex buffer draw list provides a 2D drawing context
3217  with antialiasing functionality which takes basic filled or outlined shapes
3218  or a path and outputs vertexes, elements and draw commands.
3219  The actual draw list API is not required to be used directly while using this
3220  library since converting the default library draw command output is done by
3221  just calling `nk_convert` but I decided to still make this library accessible
3222  since it can be useful.
3223 
3224  The draw list is based on a path buffering and polygon and polyline
3225  rendering API which allows a lot of ways to draw 2D content to screen.
3226  In fact it is probably more powerful than needed but allows even more crazy
3227  things than this library provides by default.
3228 */
3229 typedef nk_ushort nk_draw_index;
3230 enum nk_draw_list_stroke {
3231  NK_STROKE_OPEN = nk_false,
3232  /* build up path has no connection back to the beginning */
3233  NK_STROKE_CLOSED = nk_true
3234  /* build up path has a connection back to the beginning */
3235 };
3236 
3237 enum nk_draw_vertex_layout_attribute {
3238  NK_VERTEX_POSITION,
3239  NK_VERTEX_COLOR,
3240  NK_VERTEX_TEXCOORD,
3241  NK_VERTEX_ATTRIBUTE_COUNT
3242 };
3243 
3244 enum nk_draw_vertex_layout_format {
3245  NK_FORMAT_SCHAR,
3246  NK_FORMAT_SSHORT,
3247  NK_FORMAT_SINT,
3248  NK_FORMAT_UCHAR,
3249  NK_FORMAT_USHORT,
3250  NK_FORMAT_UINT,
3251  NK_FORMAT_FLOAT,
3252  NK_FORMAT_DOUBLE,
3253 
3254 NK_FORMAT_COLOR_BEGIN,
3255  NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
3256  NK_FORMAT_R16G15B16,
3257  NK_FORMAT_R32G32B32,
3258 
3259  NK_FORMAT_R8G8B8A8,
3260  NK_FORMAT_B8G8R8A8,
3261  NK_FORMAT_R16G15B16A16,
3262  NK_FORMAT_R32G32B32A32,
3263  NK_FORMAT_R32G32B32A32_FLOAT,
3264  NK_FORMAT_R32G32B32A32_DOUBLE,
3265 
3266  NK_FORMAT_RGB32,
3267  NK_FORMAT_RGBA32,
3268 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
3269  NK_FORMAT_COUNT
3270 };
3271 
3272 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
3273 struct nk_draw_vertex_layout_element {
3274  enum nk_draw_vertex_layout_attribute attribute;
3275  enum nk_draw_vertex_layout_format format;
3276  nk_size offset;
3277 };
3278 
3279 struct nk_draw_command {
3280  unsigned int elem_count;
3281  /* number of elements in the current draw batch */
3282  struct nk_rect clip_rect;
3283  /* current screen clipping rectangle */
3284  nk_handle texture;
3285  /* current texture to set */
3286 #ifdef NK_INCLUDE_COMMAND_USERDATA
3287  nk_handle userdata;
3288 #endif
3289 };
3290 
3291 struct nk_draw_list {
3292  struct nk_rect clip_rect;
3293  struct nk_vec2 circle_vtx[12];
3294  struct nk_convert_config config;
3295 
3296  struct nk_buffer *buffer;
3297  struct nk_buffer *vertices;
3298  struct nk_buffer *elements;
3299 
3300  unsigned int element_count;
3301  unsigned int vertex_count;
3302  unsigned int cmd_count;
3303  nk_size cmd_offset;
3304 
3305  unsigned int path_count;
3306  unsigned int path_offset;
3307 
3308  enum nk_anti_aliasing line_AA;
3309  enum nk_anti_aliasing shape_AA;
3310 
3311 #ifdef NK_INCLUDE_COMMAND_USERDATA
3312  nk_handle userdata;
3313 #endif
3314 };
3315 
3316 /* draw list */
3317 NK_API void nk_draw_list_init(struct nk_draw_list*);
3318 NK_API void nk_draw_list_setup(struct nk_draw_list*, const struct nk_convert_config*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, enum nk_anti_aliasing line_aa,enum nk_anti_aliasing shape_aa);
3319 NK_API void nk_draw_list_clear(struct nk_draw_list*);
3320 
3321 /* drawing */
3322 #define nk_draw_list_foreach(cmd, can, b) for((cmd)=nk__draw_list_begin(can, b); (cmd)!=0; (cmd)=nk__draw_list_next(cmd, b, can))
3323 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
3324 NK_API const struct nk_draw_command* nk__draw_list_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_draw_list*);
3325 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
3326 NK_API void nk_draw_list_clear(struct nk_draw_list *list);
3327 
3328 /* path */
3329 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
3330 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
3331 NK_API void nk_draw_list_path_arc_to_fast(struct nk_draw_list*, struct nk_vec2 center, float radius, int a_min, int a_max);
3332 NK_API void nk_draw_list_path_arc_to(struct nk_draw_list*, struct nk_vec2 center, float radius, float a_min, float a_max, unsigned int segments);
3333 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
3334 NK_API void nk_draw_list_path_curve_to(struct nk_draw_list*, struct nk_vec2 p2, struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments);
3335 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
3336 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
3337 
3338 /* stroke */
3339 NK_API void nk_draw_list_stroke_line(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_color, float thickness);
3340 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
3341 NK_API void nk_draw_list_stroke_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color, float thickness);
3342 NK_API void nk_draw_list_stroke_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color, unsigned int segs, float thickness);
3343 NK_API void nk_draw_list_stroke_curve(struct nk_draw_list*, struct nk_vec2 p0, struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, struct nk_color, unsigned int segments, float thickness);
3344 NK_API void nk_draw_list_stroke_poly_line(struct nk_draw_list*, const struct nk_vec2 *pnts, const unsigned int cnt, struct nk_color, enum nk_draw_list_stroke, float thickness, enum nk_anti_aliasing);
3345 
3346 /* fill */
3347 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
3348 NK_API void nk_draw_list_fill_rect_multi_color(struct nk_draw_list*, struct nk_rect rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom);
3349 NK_API void nk_draw_list_fill_triangle(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, struct nk_vec2 c, struct nk_color);
3350 NK_API void nk_draw_list_fill_circle(struct nk_draw_list*, struct nk_vec2 center, float radius, struct nk_color col, unsigned int segs);
3351 NK_API void nk_draw_list_fill_poly_convex(struct nk_draw_list*, const struct nk_vec2 *points, const unsigned int count, struct nk_color, enum nk_anti_aliasing);
3352 
3353 /* misc */
3354 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
3355 NK_API void nk_draw_list_add_text(struct nk_draw_list*, const struct nk_user_font*, struct nk_rect, const char *text, int len, float font_height, struct nk_color);
3356 #ifdef NK_INCLUDE_COMMAND_USERDATA
3357 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
3358 #endif
3359 
3360 #endif
3361 
3362 /* ===============================================================
3363  *
3364  * GUI
3365  *
3366  * ===============================================================*/
3370 };
3371 
3373  struct nk_image image;
3374  struct nk_color color;
3375 };
3376 
3380 };
3381 
3383  struct nk_color color;
3385 };
3386 
3388  /* background */
3393 
3394  /* text */
3399  nk_flags text_alignment;
3400 
3401  /* properties */
3402  float border;
3403  float rounding;
3407 
3408  /* optional user callbacks */
3409  nk_handle userdata;
3411  void(*draw_end)(struct nk_command_buffer*, nk_handle userdata);
3412 };
3413 
3415  /* background */
3420 
3421  /* cursor */
3424 
3425  /* text */
3430  nk_flags text_alignment;
3431 
3432  /* properties */
3435  float spacing;
3436  float border;
3437 
3438  /* optional user callbacks */
3439  nk_handle userdata;
3440  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3441  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3442 };
3443 
3445  /* background (inactive) */
3449 
3450  /* background (active) */
3454 
3455  /* text color (inactive) */
3459 
3460  /* text color (active) */
3465  nk_flags text_alignment;
3466 
3467  /* properties */
3468  float rounding;
3472 
3473  /* optional user callbacks */
3474  nk_handle userdata;
3475  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3476  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3477 };
3478 
3480  /* background */
3485 
3486  /* background bar */
3491 
3492  /* cursor */
3496 
3497  /* properties */
3498  float border;
3499  float rounding;
3500  float bar_height;
3504 
3505  /* optional buttons */
3511 
3512  /* optional user callbacks */
3513  nk_handle userdata;
3514  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3515  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3516 };
3517 
3519  /* background */
3524 
3525  /* cursor */
3530 
3531  /* properties */
3532  float rounding;
3533  float border;
3537 
3538  /* optional user callbacks */
3539  nk_handle userdata;
3540  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3541  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3542 };
3543 
3545  /* background */
3550 
3551  /* cursor */
3556 
3557  /* properties */
3558  float border;
3559  float rounding;
3563 
3564  /* optional buttons */
3570 
3571  /* optional user callbacks */
3572  nk_handle userdata;
3573  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3574  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3575 };
3576 
3578  /* background */
3584 
3585  /* cursor */
3590 
3591  /* text (unselected) */
3595 
3596  /* text (selected) */
3601 
3602  /* properties */
3603  float border;
3604  float rounding;
3609 };
3610 
3612  /* background */
3617 
3618  /* text */
3622 
3623  /* symbols */
3626 
3627  /* properties */
3628  float border;
3629  float rounding;
3631 
3635 
3636  /* optional user callbacks */
3637  nk_handle userdata;
3638  void(*draw_begin)(struct nk_command_buffer*, nk_handle);
3639  void(*draw_end)(struct nk_command_buffer*, nk_handle);
3640 };
3641 
3643  /* colors */
3647  struct nk_color color;
3648 
3649  /* properties */
3650  float border;
3651  float rounding;
3653 };
3654 
3656  /* background */
3661 
3662  /* label */
3666 
3667  /* symbol */
3671 
3672  /* button */
3677 
3678  /* properties */
3679  float border;
3680  float rounding;
3684 };
3685 
3687  /* background */
3690  struct nk_color text;
3691 
3692  /* button */
3699 
3700  /* properties */
3701  float border;
3702  float rounding;
3703  float indent;
3706 };
3707 
3711 };
3713  /* background */
3717 
3718  /* button */
3724 
3725  /* title */
3729 
3730  /* properties */
3735 };
3736 
3741 
3750 
3751  float border;
3759 
3760  float rounding;
3764 
3772 };
3773 
3774 struct nk_style {
3775  const struct nk_user_font *font;
3777  const struct nk_cursor *cursor_active;
3780 
3798 };
3799 
3803 
3804 /*==============================================================
3805  * PANEL
3806  * =============================================================*/
3807 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
3808 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
3809 #endif
3810 #ifndef NK_CHART_MAX_SLOT
3811 #define NK_CHART_MAX_SLOT 4
3812 #endif
3813 
3822 };
3827 };
3828 
3831  struct nk_color color;
3833  float min, max, range;
3834  int count;
3835  struct nk_vec2 last;
3836  int index;
3837 };
3838 
3839 struct nk_chart {
3840  int slot;
3841  float x, y, w, h;
3843 };
3844 
3856 };
3859  int index;
3860  float height;
3861  float min_height;
3862  int columns;
3863  const float *ratio;
3864  float item_width;
3867  float filled;
3868  struct nk_rect item;
3871 };
3872 
3874  nk_size begin;
3875  nk_size parent;
3876  nk_size last;
3877  nk_size end;
3878  int active;
3879 };
3880 
3882  float x, y, w, h;
3884 };
3885 
3886 struct nk_panel {
3888  nk_flags flags;
3889  struct nk_rect bounds;
3890  nk_uint *offset_x;
3891  nk_uint *offset_y;
3892  float at_x, at_y, max_x;
3895  float border;
3896  unsigned int has_scrolling;
3897  struct nk_rect clip;
3900  struct nk_chart chart;
3902  struct nk_panel *parent;
3903 };
3904 
3905 /*==============================================================
3906  * WINDOW
3907  * =============================================================*/
3908 #ifndef NK_WINDOW_MAX_NAME
3909 #define NK_WINDOW_MAX_NAME 64
3910 #endif
3911 
3912 struct nk_table;
3916  /* special window type growing up in height while being filled to a certain maximum height */
3918  /* sets window widgets into a read only mode and does not allow input changes */
3920  /* prevents all interaction caused by input to either window or widgets inside */
3922  /* Hides window and stops any window interaction and drawing */
3924  /* Directly closes and frees the window at the end of the frame */
3926  /* marks the window as minimized */
3928  /* Removes read only mode at the end of the window */
3929 };
3930 
3932  struct nk_window *win;
3935  nk_hash name;
3936  int active;
3937  unsigned combo_count;
3938  unsigned con_count, con_old;
3939  unsigned active_con;
3940  struct nk_rect header;
3941 };
3942 
3944  nk_hash name;
3945  unsigned int seq;
3946  unsigned int old;
3947  int active, prev;
3948  int cursor;
3950  int sel_end;
3952  unsigned char mode;
3953  unsigned char single_line;
3954 };
3955 
3957  int active, prev;
3959  int length;
3960  int cursor;
3963  nk_hash name;
3964  unsigned int seq;
3965  unsigned int old;
3966  int state;
3967 };
3968 
3969 struct nk_window {
3970  unsigned int seq;
3971  nk_hash name;
3973  nk_flags flags;
3974 
3975  struct nk_rect bounds;
3978  struct nk_panel *layout;
3980 
3981  /* persistent widget state */
3985  unsigned int scrolled;
3986 
3987  struct nk_table *tables;
3988  unsigned int table_count;
3989 
3990  /* window list hooks */
3991  struct nk_window *next;
3992  struct nk_window *prev;
3994 };
3995 
3996 /*==============================================================
3997  * STACK
3998  * =============================================================*/
3999 /* The style modifier stack can be used to temporarily change a
4000  * property inside `nk_style`. For example if you want a special
4001  * red button you can temporarily push the old button color onto a stack
4002  * draw the button with a red color and then you just pop the old color
4003  * back from the stack:
4004  *
4005  * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
4006  * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
4007  * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
4008  * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
4009  *
4010  * nk_button(...);
4011  *
4012  * nk_style_pop_style_item(ctx);
4013  * nk_style_pop_style_item(ctx);
4014  * nk_style_pop_style_item(ctx);
4015  * nk_style_pop_vec2(ctx);
4016  *
4017  * Nuklear has a stack for style_items, float properties, vector properties,
4018  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
4019  * which can be changed at compile time.
4020  */
4021 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
4022 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
4023 #endif
4024 
4025 #ifndef NK_FONT_STACK_SIZE
4026 #define NK_FONT_STACK_SIZE 8
4027 #endif
4028 
4029 #ifndef NK_STYLE_ITEM_STACK_SIZE
4030 #define NK_STYLE_ITEM_STACK_SIZE 16
4031 #endif
4032 
4033 #ifndef NK_FLOAT_STACK_SIZE
4034 #define NK_FLOAT_STACK_SIZE 32
4035 #endif
4036 
4037 #ifndef NK_VECTOR_STACK_SIZE
4038 #define NK_VECTOR_STACK_SIZE 16
4039 #endif
4040 
4041 #ifndef NK_FLAGS_STACK_SIZE
4042 #define NK_FLAGS_STACK_SIZE 32
4043 #endif
4044 
4045 #ifndef NK_COLOR_STACK_SIZE
4046 #define NK_COLOR_STACK_SIZE 32
4047 #endif
4048 
4049 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
4050  struct nk_config_stack_##name##_element {\
4051  prefix##_##type *address;\
4052  prefix##_##type old_value;\
4053  }
4054 #define NK_CONFIG_STACK(type,size)\
4055  struct nk_config_stack_##type {\
4056  int head;\
4057  struct nk_config_stack_##type##_element elements[size];\
4058  }
4059 
4060 #define nk_float float
4061 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
4062 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
4063 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
4065 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color);
4066 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
4067 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
4068 
4076 
4078  struct nk_config_stack_style_item style_items;
4079  struct nk_config_stack_float floats;
4080  struct nk_config_stack_vec2 vectors;
4081  struct nk_config_stack_flags flags;
4082  struct nk_config_stack_color colors;
4083  struct nk_config_stack_user_font fonts;
4084  struct nk_config_stack_button_behavior button_behaviors;
4085 };
4086 
4087 /*==============================================================
4088  * CONTEXT
4089  * =============================================================*/
4090 #define NK_VALUE_PAGE_CAPACITY \
4091  (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
4092 
4093 struct nk_table {
4094  unsigned int seq;
4095  unsigned int size;
4098  struct nk_table *next, *prev;
4099 };
4100 
4102  struct nk_table tbl;
4103  struct nk_panel pan;
4104  struct nk_window win;
4105 };
4106 
4111 };
4112 
4113 struct nk_page {
4114  unsigned int size;
4115  struct nk_page *next;
4117 };
4118 
4119 struct nk_pool {
4122  unsigned int page_count;
4123  struct nk_page *pages;
4125  unsigned capacity;
4126  nk_size size;
4127  nk_size cap;
4128 };
4129 
4130 struct nk_context {
4131 /* public: can be accessed freely */
4132  struct nk_input input;
4133  struct nk_style style;
4140 
4141 /* private:
4142  should only be accessed if you
4143  know what you are doing */
4144 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4145  struct nk_draw_list draw_list;
4146 #endif
4147 #ifdef NK_INCLUDE_COMMAND_USERDATA
4148  nk_handle userdata;
4149 #endif
4150  /* text editor objects are quite big because of an internal
4151  * undo/redo stack. Therefore it does not make sense to have one for
4152  * each window for temporary use cases, so I only provide *one* instance
4153  * for all windows. This works because the content is cleared anyway */
4155  /* draw buffer used for overlay drawing operation like cursor */
4157 
4158  /* windows */
4159  int build;
4161  struct nk_pool pool;
4162  struct nk_window *begin;
4163  struct nk_window *end;
4167  unsigned int count;
4168  unsigned int seq;
4169 };
4170 
4171 /* ==============================================================
4172  * MATH
4173  * =============================================================== */
4174 #define NK_PI 3.141592654f
4175 #define NK_UTF_INVALID 0xFFFD
4176 #define NK_MAX_FLOAT_PRECISION 2
4177 
4178 #define NK_UNUSED(x) ((void)(x))
4179 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
4180 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
4181 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
4182 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
4183 #define NK_INBOX(px, py, x, y, w, h)\
4184  (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
4185 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
4186  (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
4187 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
4188  (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
4189 
4190 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
4191 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
4192 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
4193 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
4194 
4195 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
4196 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
4197 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
4198 
4199 /* ==============================================================
4200  * ALIGNMENT
4201  * =============================================================== */
4202 /* Pointer to Integer type conversion for pointer alignment */
4203 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
4204 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
4205 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
4206 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
4207 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
4208 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
4209 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
4210 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
4211 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
4212 #else /* generates warning but works */
4213 # define NK_UINT_TO_PTR(x) ((void*)(x))
4214 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
4215 #endif
4216 
4217 #define NK_ALIGN_PTR(x, mask)\
4218  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
4219 #define NK_ALIGN_PTR_BACK(x, mask)\
4220  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
4221 
4222 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
4223 #define NK_CONTAINER_OF(ptr,type,member)\
4224  (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
4225 
4226 #ifdef __cplusplus
4227 }
4228 #endif
4229 
4230 #ifdef __cplusplus
4231 template<typename T> struct nk_alignof;
4232 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
4233 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
4234 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
4235  diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
4236 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
4237 #elif defined(_MSC_VER)
4238 #define NK_ALIGNOF(t) (__alignof(t))
4239 #else
4240 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
4241 #endif
4242 
4243 #endif /* NK_H_ */
4244 /*
4245  * ==============================================================
4246  *
4247  * IMPLEMENTATION
4248  *
4249  * ===============================================================
4250  */
4251 #ifdef NK_IMPLEMENTATION
4252 
4253 #ifndef NK_POOL_DEFAULT_CAPACITY
4254 #define NK_POOL_DEFAULT_CAPACITY 16
4255 #endif
4256 
4257 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
4258 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
4259 #endif
4260 
4261 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
4262 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
4263 #endif
4264 
4265 /* standard library headers */
4266 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4267 #include <stdlib.h> /* malloc, free */
4268 #endif
4269 #ifdef NK_INCLUDE_STANDARD_IO
4270 #include <stdio.h> /* fopen, fclose,... */
4271 #endif
4272 #ifdef NK_INCLUDE_STANDARD_VARARGS
4273 #include <stdarg.h> /* valist, va_start, va_end, ... */
4274 #endif
4275 #ifndef NK_ASSERT
4276 #include <assert.h>
4277 #define NK_ASSERT(expr) assert(expr)
4278 #endif
4279 
4280 #ifndef NK_MEMSET
4281 #define NK_MEMSET nk_memset
4282 #endif
4283 #ifndef NK_MEMCPY
4284 #define NK_MEMCPY nk_memcopy
4285 #endif
4286 #ifndef NK_SQRT
4287 #define NK_SQRT nk_sqrt
4288 #endif
4289 #ifndef NK_SIN
4290 #define NK_SIN nk_sin
4291 #endif
4292 #ifndef NK_COS
4293 #define NK_COS nk_cos
4294 #endif
4295 #ifndef NK_STRTOD
4296 #define NK_STRTOD nk_strtod
4297 #endif
4298 #ifndef NK_DTOA
4299 #define NK_DTOA nk_dtoa
4300 #endif
4301 
4302 #define NK_DEFAULT (-1)
4303 
4304 #ifndef NK_VSNPRINTF
4305 /* If your compiler does support `vsnprintf` I would highly recommend
4306  * defining this to vsnprintf instead since `vsprintf` is basically
4307  * unbelievable unsafe and should *NEVER* be used. But I have to support
4308  * it since C89 only provides this unsafe version. */
4309  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
4310  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
4311  (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
4312  (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
4313  defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
4314  #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
4315  #else
4316  #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
4317  #endif
4318 #endif
4319 
4320 #define NK_SCHAR_MIN (-127)
4321 #define NK_SCHAR_MAX 127
4322 #define NK_UCHAR_MIN 0
4323 #define NK_UCHAR_MAX 256
4324 #define NK_SSHORT_MIN (-32767)
4325 #define NK_SSHORT_MAX 32767
4326 #define NK_USHORT_MIN 0
4327 #define NK_USHORT_MAX 65535
4328 #define NK_SINT_MIN (-2147483647)
4329 #define NK_SINT_MAX 2147483647
4330 #define NK_UINT_MIN 0
4331 #define NK_UINT_MAX 4294967295u
4332 
4333 /* Make sure correct type size:
4334  * This will fire with a negative subscript error if the type sizes
4335  * are set incorrectly by the compiler, and compile out if not */
4336 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
4337 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
4338 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
4339 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
4340 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
4341 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
4342 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
4343 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
4344 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
4345 
4346 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
4347 #define NK_FLOAT_PRECISION 0.00000000000001
4348 
4349 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
4350 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
4351 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
4352 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
4353 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
4354 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
4355 
4356 /*
4357  * ==============================================================
4358  *
4359  * MATH
4360  *
4361  * ===============================================================
4362  */
4363 /* Since nuklear is supposed to work on all systems providing floating point
4364  math without any dependencies I also had to implement my own math functions
4365  for sqrt, sin and cos. Since the actual highly accurate implementations for
4366  the standard library functions are quite complex and I do not need high
4367  precision for my use cases I use approximations.
4368 
4369  Sqrt
4370  ----
4371  For square root nuklear uses the famous fast inverse square root:
4372  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
4373  slightly tweaked magic constant. While on today's hardware it is
4374  probably not faster it is still fast and accurate enough for
4375  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
4376 
4377  Sine/Cosine
4378  -----------
4379  All constants inside both function are generated Remez's minimax
4380  approximations for value range 0...2*PI. The reason why I decided to
4381  approximate exactly that range is that nuklear only needs sine and
4382  cosine to generate circles which only requires that exact range.
4383  In addition I used Remez instead of Taylor for additional precision:
4384  www.lolengine.net/blog/2011/12/21/better-function-approximations.
4385 
4386  The tool I used to generate constants for both sine and cosine
4387  (it can actually approximate a lot more functions) can be
4388  found here: www.lolengine.net/wiki/oss/lolremez
4389 */
4390 NK_INTERN float
4391 nk_inv_sqrt(float number)
4392 {
4393  float x2;
4394  const float threehalfs = 1.5f;
4395  union {nk_uint i; float f;} conv = {0};
4396  conv.f = number;
4397  x2 = number * 0.5f;
4398  conv.i = 0x5f375A84 - (conv.i >> 1);
4399  conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
4400  return conv.f;
4401 }
4402 
4403 NK_INTERN float
4404 nk_sqrt(float x)
4405 {
4406  return x * nk_inv_sqrt(x);
4407 }
4408 
4409 NK_INTERN float
4410 nk_sin(float x)
4411 {
4412  NK_STORAGE const float a0 = +1.91059300966915117e-31f;
4413  NK_STORAGE const float a1 = +1.00086760103908896f;
4414  NK_STORAGE const float a2 = -1.21276126894734565e-2f;
4415  NK_STORAGE const float a3 = -1.38078780785773762e-1f;
4416  NK_STORAGE const float a4 = -2.67353392911981221e-2f;
4417  NK_STORAGE const float a5 = +2.08026600266304389e-2f;
4418  NK_STORAGE const float a6 = -3.03996055049204407e-3f;
4419  NK_STORAGE const float a7 = +1.38235642404333740e-4f;
4420  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4421 }
4422 
4423 NK_INTERN float
4424 nk_cos(float x)
4425 {
4426  NK_STORAGE const float a0 = +1.00238601909309722f;
4427  NK_STORAGE const float a1 = -3.81919947353040024e-2f;
4428  NK_STORAGE const float a2 = -3.94382342128062756e-1f;
4429  NK_STORAGE const float a3 = -1.18134036025221444e-1f;
4430  NK_STORAGE const float a4 = +1.07123798512170878e-1f;
4431  NK_STORAGE const float a5 = -1.86637164165180873e-2f;
4432  NK_STORAGE const float a6 = +9.90140908664079833e-4f;
4433  NK_STORAGE const float a7 = -5.23022132118824778e-14f;
4434  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4435 }
4436 
4437 NK_INTERN nk_uint
4438 nk_round_up_pow2(nk_uint v)
4439 {
4440  v--;
4441  v |= v >> 1;
4442  v |= v >> 2;
4443  v |= v >> 4;
4444  v |= v >> 8;
4445  v |= v >> 16;
4446  v++;
4447  return v;
4448 }
4449 
4450 NK_API struct nk_rect
4452 {
4453  return nk_null_rect;
4454 }
4455 
4456 NK_API struct nk_rect
4457 nk_rect(float x, float y, float w, float h)
4458 {
4459  struct nk_rect r;
4460  r.x = x; r.y = y;
4461  r.w = w; r.h = h;
4462  return r;
4463 }
4464 
4465 NK_API struct nk_rect
4466 nk_recti(int x, int y, int w, int h)
4467 {
4468  struct nk_rect r;
4469  r.x = (float)x;
4470  r.y = (float)y;
4471  r.w = (float)w;
4472  r.h = (float)h;
4473  return r;
4474 }
4475 
4476 NK_API struct nk_rect
4477 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
4478 {
4479  return nk_rect(pos.x, pos.y, size.x, size.y);
4480 }
4481 
4482 NK_API struct nk_rect
4483 nk_rectv(const float *r)
4484 {
4485  return nk_rect(r[0], r[1], r[2], r[3]);
4486 }
4487 
4488 NK_API struct nk_rect
4489 nk_rectiv(const int *r)
4490 {
4491  return nk_recti(r[0], r[1], r[2], r[3]);
4492 }
4493 
4494 NK_API struct nk_vec2
4495 nk_rect_pos(struct nk_rect r)
4496 {
4497  struct nk_vec2 ret;
4498  ret.x = r.x; ret.y = r.y;
4499  return ret;
4500 }
4501 
4502 NK_API struct nk_vec2
4503 nk_rect_size(struct nk_rect r)
4504 {
4505  struct nk_vec2 ret;
4506  ret.x = r.w; ret.y = r.h;
4507  return ret;
4508 }
4509 
4510 NK_INTERN struct nk_rect
4511 nk_shrink_rect(struct nk_rect r, float amount)
4512 {
4513  struct nk_rect res;
4514  r.w = NK_MAX(r.w, 2 * amount);
4515  r.h = NK_MAX(r.h, 2 * amount);
4516  res.x = r.x + amount;
4517  res.y = r.y + amount;
4518  res.w = r.w - 2 * amount;
4519  res.h = r.h - 2 * amount;
4520  return res;
4521 }
4522 
4523 NK_INTERN struct nk_rect
4524 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
4525 {
4526  r.w = NK_MAX(r.w, 2 * pad.x);
4527  r.h = NK_MAX(r.h, 2 * pad.y);
4528  r.x += pad.x; r.y += pad.y;
4529  r.w -= 2 * pad.x;
4530  r.h -= 2 * pad.y;
4531  return r;
4532 }
4533 
4534 NK_API struct nk_vec2
4535 nk_vec2(float x, float y)
4536 {
4537  struct nk_vec2 ret;
4538  ret.x = x; ret.y = y;
4539  return ret;
4540 }
4541 
4542 NK_API struct nk_vec2
4543 nk_vec2i(int x, int y)
4544 {
4545  struct nk_vec2 ret;
4546  ret.x = (float)x;
4547  ret.y = (float)y;
4548  return ret;
4549 }
4550 
4551 NK_API struct nk_vec2
4552 nk_vec2v(const float *v)
4553 {
4554  return nk_vec2(v[0], v[1]);
4555 }
4556 
4557 NK_API struct nk_vec2
4558 nk_vec2iv(const int *v)
4559 {
4560  return nk_vec2i(v[0], v[1]);
4561 }
4562 
4563 /*
4564  * ==============================================================
4565  *
4566  * UTIL
4567  *
4568  * ===============================================================
4569  */
4570 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
4571 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
4572 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
4573 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
4574 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
4575 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
4576 
4577 NK_INTERN void*
4578 nk_memcopy(void *dst0, const void *src0, nk_size length)
4579 {
4580  nk_ptr t;
4581  char *dst = (char*)dst0;
4582  const char *src = (const char*)src0;
4583  if (length == 0 || dst == src)
4584  goto done;
4585 
4586  #define nk_word int
4587  #define nk_wsize sizeof(nk_word)
4588  #define nk_wmask (nk_wsize-1)
4589  #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
4590  #define NK_TLOOP1(s) do { s; } while (--t)
4591 
4592  if (dst < src) {
4593  t = (nk_ptr)src; /* only need low bits */
4594  if ((t | (nk_ptr)dst) & nk_wmask) {
4595  if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
4596  t = length;
4597  else
4598  t = nk_wsize - (t & nk_wmask);
4599  length -= t;
4600  NK_TLOOP1(*dst++ = *src++);
4601  }
4602  t = length / nk_wsize;
4603  NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
4604  src += nk_wsize; dst += nk_wsize);
4605  t = length & nk_wmask;
4606  NK_TLOOP(*dst++ = *src++);
4607  } else {
4608  src += length;
4609  dst += length;
4610  t = (nk_ptr)src;
4611  if ((t | (nk_ptr)dst) & nk_wmask) {
4612  if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
4613  t = length;
4614  else
4615  t &= nk_wmask;
4616  length -= t;
4617  NK_TLOOP1(*--dst = *--src);
4618  }
4619  t = length / nk_wsize;
4620  NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
4621  *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
4622  t = length & nk_wmask;
4623  NK_TLOOP(*--dst = *--src);
4624  }
4625  #undef nk_word
4626  #undef nk_wsize
4627  #undef nk_wmask
4628  #undef NK_TLOOP
4629  #undef NK_TLOOP1
4630 done:
4631  return (dst0);
4632 }
4633 
4634 NK_INTERN void
4635 nk_memset(void *ptr, int c0, nk_size size)
4636 {
4637  #define nk_word unsigned
4638  #define nk_wsize sizeof(nk_word)
4639  #define nk_wmask (nk_wsize - 1)
4640  nk_byte *dst = (nk_byte*)ptr;
4641  unsigned c = 0;
4642  nk_size t = 0;
4643 
4644  if ((c = (nk_byte)c0) != 0) {
4645  c = (c << 8) | c; /* at least 16-bits */
4646  if (sizeof(unsigned int) > 2)
4647  c = (c << 16) | c; /* at least 32-bits*/
4648  }
4649 
4650  /* too small of a word count */
4651  dst = (nk_byte*)ptr;
4652  if (size < 3 * nk_wsize) {
4653  while (size--) *dst++ = (nk_byte)c0;
4654  return;
4655  }
4656 
4657  /* align destination */
4658  if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
4659  t = nk_wsize -t;
4660  size -= t;
4661  do {
4662  *dst++ = (nk_byte)c0;
4663  } while (--t != 0);
4664  }
4665 
4666  /* fill word */
4667  t = size / nk_wsize;
4668  do {
4669  *(nk_word*)((void*)dst) = c;
4670  dst += nk_wsize;
4671  } while (--t != 0);
4672 
4673  /* fill trailing bytes */
4674  t = (size & nk_wmask);
4675  if (t != 0) {
4676  do {
4677  *dst++ = (nk_byte)c0;
4678  } while (--t != 0);
4679  }
4680 
4681  #undef nk_word
4682  #undef nk_wsize
4683  #undef nk_wmask
4684 }
4685 
4686 NK_INTERN void
4687 nk_zero(void *ptr, nk_size size)
4688 {
4689  NK_ASSERT(ptr);
4690  NK_MEMSET(ptr, 0, size);
4691 }
4692 
4693 NK_API int
4694 nk_strlen(const char *str)
4695 {
4696  int siz = 0;
4697  NK_ASSERT(str);
4698  while (str && *str++ != '\0') siz++;
4699  return siz;
4700 }
4701 
4702 NK_API int
4703 nk_strtoi(const char *str, const char **endptr)
4704 {
4705  int neg = 1;
4706  const char *p = str;
4707  int value = 0;
4708 
4709  NK_ASSERT(str);
4710  if (!str) return 0;
4711 
4712  /* skip whitespace */
4713  while (*p == ' ') p++;
4714  if (*p == '-') {
4715  neg = -1;
4716  p++;
4717  }
4718  while (*p && *p >= '0' && *p <= '9') {
4719  value = value * 10 + (int) (*p - '0');
4720  p++;
4721  }
4722  if (endptr)
4723  *endptr = p;
4724  return neg*value;
4725 }
4726 
4727 NK_API double
4728 nk_strtod(const char *str, const char **endptr)
4729 {
4730  double m;
4731  double neg = 1.0;
4732  const char *p = str;
4733  double value = 0;
4734  double number = 0;
4735 
4736  NK_ASSERT(str);
4737  if (!str) return 0;
4738 
4739  /* skip whitespace */
4740  while (*p == ' ') p++;
4741  if (*p == '-') {
4742  neg = -1.0;
4743  p++;
4744  }
4745 
4746  while (*p && *p != '.' && *p != 'e') {
4747  value = value * 10.0 + (double) (*p - '0');
4748  p++;
4749  }
4750 
4751  if (*p == '.') {
4752  p++;
4753  for(m = 0.1; *p && *p != 'e'; p++ ) {
4754  value = value + (double) (*p - '0') * m;
4755  m *= 0.1;
4756  }
4757  }
4758  if (*p == 'e') {
4759  int i, pow, div;
4760  p++;
4761  if (*p == '-') {
4762  div = nk_true;
4763  p++;
4764  } else if (*p == '+') {
4765  div = nk_false;
4766  p++;
4767  } else div = nk_false;
4768 
4769  for (pow = 0; *p; p++)
4770  pow = pow * 10 + (int) (*p - '0');
4771 
4772  for (m = 1.0, i = 0; i < pow; i++)
4773  m *= 10.0;
4774 
4775  if (div)
4776  value /= m;
4777  else value *= m;
4778  }
4779  number = value * neg;
4780  if (endptr)
4781  *endptr = p;
4782  return number;
4783 }
4784 
4785 NK_API float
4786 nk_strtof(const char *str, const char **endptr)
4787 {
4788  float float_value;
4789  double double_value;
4790  double_value = NK_STRTOD(str, endptr);
4791  float_value = (float)double_value;
4792  return float_value;
4793 }
4794 
4795 NK_API int
4796 nk_stricmp(const char *s1, const char *s2)
4797 {
4798  nk_int c1,c2,d;
4799  do {
4800  c1 = *s1++;
4801  c2 = *s2++;
4802  d = c1 - c2;
4803  while (d) {
4804  if (c1 <= 'Z' && c1 >= 'A') {
4805  d += ('a' - 'A');
4806  if (!d) break;
4807  }
4808  if (c2 <= 'Z' && c2 >= 'A') {
4809  d -= ('a' - 'A');
4810  if (!d) break;
4811  }
4812  return ((d >= 0) << 1) - 1;
4813  }
4814  } while (c1);
4815  return 0;
4816 }
4817 
4818 NK_API int
4819 nk_stricmpn(const char *s1, const char *s2, int n)
4820 {
4821  int c1,c2,d;
4822  NK_ASSERT(n >= 0);
4823  do {
4824  c1 = *s1++;
4825  c2 = *s2++;
4826  if (!n--) return 0;
4827 
4828  d = c1 - c2;
4829  while (d) {
4830  if (c1 <= 'Z' && c1 >= 'A') {
4831  d += ('a' - 'A');
4832  if (!d) break;
4833  }
4834  if (c2 <= 'Z' && c2 >= 'A') {
4835  d -= ('a' - 'A');
4836  if (!d) break;
4837  }
4838  return ((d >= 0) << 1) - 1;
4839  }
4840  } while (c1);
4841  return 0;
4842 }
4843 
4844 NK_INTERN int
4845 nk_str_match_here(const char *regexp, const char *text)
4846 {
4847  if (regexp[0] == '\0')
4848  return 1;
4849  if (regexp[1] == '*')
4850  return nk_str_match_star(regexp[0], regexp+2, text);
4851  if (regexp[0] == '$' && regexp[1] == '\0')
4852  return *text == '\0';
4853  if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
4854  return nk_str_match_here(regexp+1, text+1);
4855  return 0;
4856 }
4857 
4858 NK_INTERN int
4859 nk_str_match_star(int c, const char *regexp, const char *text)
4860 {
4861  do {/* a '* matches zero or more instances */
4862  if (nk_str_match_here(regexp, text))
4863  return 1;
4864  } while (*text != '\0' && (*text++ == c || c == '.'));
4865  return 0;
4866 }
4867 
4868 NK_API int
4869 nk_strfilter(const char *text, const char *regexp)
4870 {
4871  /*
4872  c matches any literal character c
4873  . matches any single character
4874  ^ matches the beginning of the input string
4875  $ matches the end of the input string
4876  * matches zero or more occurrences of the previous character*/
4877  if (regexp[0] == '^')
4878  return nk_str_match_here(regexp+1, text);
4879  do { /* must look even if string is empty */
4880  if (nk_str_match_here(regexp, text))
4881  return 1;
4882  } while (*text++ != '\0');
4883  return 0;
4884 }
4885 
4886 NK_API int
4887 nk_strmatch_fuzzy_text(const char *str, int str_len,
4888  const char *pattern, int *out_score)
4889 {
4890  /* Returns true if each character in pattern is found sequentially within str
4891  * if found then out_score is also set. Score value has no intrinsic meaning.
4892  * Range varies with pattern. Can only compare scores with same search pattern. */
4893 
4894  /* ------- scores --------- */
4895  /* bonus for adjacent matches */
4896  #define NK_ADJACENCY_BONUS 5
4897  /* bonus if match occurs after a separator */
4898  #define NK_SEPARATOR_BONUS 10
4899  /* bonus if match is uppercase and prev is lower */
4900  #define NK_CAMEL_BONUS 10
4901  /* penalty applied for every letter in str before the first match */
4902  #define NK_LEADING_LETTER_PENALTY (-3)
4903  /* maximum penalty for leading letters */
4904  #define NK_MAX_LEADING_LETTER_PENALTY (-9)
4905  /* penalty for every letter that doesn't matter */
4906  #define NK_UNMATCHED_LETTER_PENALTY (-1)
4907 
4908  /* loop variables */
4909  int score = 0;
4910  char const * pattern_iter = pattern;
4911  int str_iter = 0;
4912  int prev_matched = nk_false;
4913  int prev_lower = nk_false;
4914  /* true so if first letter match gets separator bonus*/
4915  int prev_separator = nk_true;
4916 
4917  /* use "best" matched letter if multiple string letters match the pattern */
4918  char const * best_letter = 0;
4919  int best_letter_score = 0;
4920 
4921  /* loop over strings */
4922  NK_ASSERT(str);
4923  NK_ASSERT(pattern);
4924  if (!str || !str_len || !pattern) return 0;
4925  while (str_iter < str_len)
4926  {
4927  const char pattern_letter = *pattern_iter;
4928  const char str_letter = str[str_iter];
4929 
4930  int next_match = *pattern_iter != '\0' &&
4931  nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
4932  int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
4933 
4934  int advanced = next_match && best_letter;
4935  int pattern_repeat = best_letter && *pattern_iter != '\0';
4936  pattern_repeat = pattern_repeat &&
4937  nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
4938 
4939  if (advanced || pattern_repeat) {
4940  score += best_letter_score;
4941  best_letter = 0;
4942  best_letter_score = 0;
4943  }
4944 
4945  if (next_match || rematch)
4946  {
4947  int new_score = 0;
4948  /* Apply penalty for each letter before the first pattern match */
4949  if (pattern_iter == pattern) {
4950  int count = (int)(&str[str_iter] - str);
4951  int penalty = NK_LEADING_LETTER_PENALTY * count;
4952  if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
4953  penalty = NK_MAX_LEADING_LETTER_PENALTY;
4954 
4955  score += penalty;
4956  }
4957 
4958  /* apply bonus for consecutive bonuses */
4959  if (prev_matched)
4960  new_score += NK_ADJACENCY_BONUS;
4961 
4962  /* apply bonus for matches after a separator */
4963  if (prev_separator)
4964  new_score += NK_SEPARATOR_BONUS;
4965 
4966  /* apply bonus across camel case boundaries */
4967  if (prev_lower && nk_is_upper(str_letter))
4968  new_score += NK_CAMEL_BONUS;
4969 
4970  /* update pattern iter IFF the next pattern letter was matched */
4971  if (next_match)
4972  ++pattern_iter;
4973 
4974  /* update best letter in str which may be for a "next" letter or a rematch */
4975  if (new_score >= best_letter_score) {
4976  /* apply penalty for now skipped letter */
4977  if (best_letter != 0)
4978  score += NK_UNMATCHED_LETTER_PENALTY;
4979 
4980  best_letter = &str[str_iter];
4981  best_letter_score = new_score;
4982  }
4983  prev_matched = nk_true;
4984  } else {
4985  score += NK_UNMATCHED_LETTER_PENALTY;
4986  prev_matched = nk_false;
4987  }
4988 
4989  /* separators should be more easily defined */
4990  prev_lower = nk_is_lower(str_letter) != 0;
4991  prev_separator = str_letter == '_' || str_letter == ' ';
4992 
4993  ++str_iter;
4994  }
4995 
4996  /* apply score for last match */
4997  if (best_letter)
4998  score += best_letter_score;
4999 
5000  /* did not match full pattern */
5001  if (*pattern_iter != '\0')
5002  return nk_false;
5003 
5004  if (out_score)
5005  *out_score = score;
5006  return nk_true;
5007 }
5008 
5009 NK_API int
5010 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
5011 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);}
5012 
5013 NK_INTERN int
5014 nk_string_float_limit(char *string, int prec)
5015 {
5016  int dot = 0;
5017  char *c = string;
5018  while (*c) {
5019  if (*c == '.') {
5020  dot = 1;
5021  c++;
5022  continue;
5023  }
5024  if (dot == (prec+1)) {
5025  *c = 0;
5026  break;
5027  }
5028  if (dot > 0) dot++;
5029  c++;
5030  }
5031  return (int)(c - string);
5032 }
5033 
5034 NK_INTERN double
5035 nk_pow(double x, int n)
5036 {
5037  /* check the sign of n */
5038  double r = 1;
5039  int plus = n >= 0;
5040  n = (plus) ? n : -n;
5041  while (n > 0) {
5042  if ((n & 1) == 1)
5043  r *= x;
5044  n /= 2;
5045  x *= x;
5046  }
5047  return plus ? r : 1.0 / r;
5048 }
5049 
5050 NK_INTERN int
5051 nk_ifloord(double x)
5052 {
5053  x = (double)((int)x - ((x < 0.0) ? 1 : 0));
5054  return (int)x;
5055 }
5056 
5057 NK_INTERN int
5058 nk_ifloorf(float x)
5059 {
5060  x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
5061  return (int)x;
5062 }
5063 
5064 NK_INTERN int
5065 nk_iceilf(float x)
5066 {
5067  if (x >= 0) {
5068  int i = (int)x;
5069  return (x > i) ? i+1: i;
5070  } else {
5071  int t = (int)x;
5072  float r = x - (float)t;
5073  return (r > 0.0f) ? t+1: t;
5074  }
5075 }
5076 
5077 NK_INTERN int
5078 nk_log10(double n)
5079 {
5080  int neg;
5081  int ret;
5082  int exp = 0;
5083 
5084  neg = (n < 0) ? 1 : 0;
5085  ret = (neg) ? (int)-n : (int)n;
5086  while ((ret / 10) > 0) {
5087  ret /= 10;
5088  exp++;
5089  }
5090  if (neg) exp = -exp;
5091  return exp;
5092 }
5093 
5094 NK_INTERN void
5095 nk_strrev_ascii(char *s)
5096 {
5097  int len = nk_strlen(s);
5098  int end = len / 2;
5099  int i = 0;
5100  char t;
5101  for (; i < end; ++i) {
5102  t = s[i];
5103  s[i] = s[len - 1 - i];
5104  s[len -1 - i] = t;
5105  }
5106 }
5107 
5108 NK_INTERN char*
5109 nk_itoa(char *s, long n)
5110 {
5111  long i = 0;
5112  if (n == 0) {
5113  s[i++] = '0';
5114  s[i] = 0;
5115  return s;
5116  }
5117  if (n < 0) {
5118  s[i++] = '-';
5119  n = -n;
5120  }
5121  while (n > 0) {
5122  s[i++] = (char)('0' + (n % 10));
5123  n /= 10;
5124  }
5125  s[i] = 0;
5126  if (s[0] == '-')
5127  ++s;
5128 
5129  nk_strrev_ascii(s);
5130  return s;
5131 }
5132 
5133 NK_INTERN char*
5134 nk_dtoa(char *s, double n)
5135 {
5136  int useExp = 0;
5137  int digit = 0, m = 0, m1 = 0;
5138  char *c = s;
5139  int neg = 0;
5140 
5141  NK_ASSERT(s);
5142  if (!s) return 0;
5143 
5144  if (n == 0.0) {
5145  s[0] = '0'; s[1] = '\0';
5146  return s;
5147  }
5148 
5149  neg = (n < 0);
5150  if (neg) n = -n;
5151 
5152  /* calculate magnitude */
5153  m = nk_log10(n);
5154  useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
5155  if (neg) *(c++) = '-';
5156 
5157  /* set up for scientific notation */
5158  if (useExp) {
5159  if (m < 0)
5160  m -= 1;
5161  n = n / (double)nk_pow(10.0, m);
5162  m1 = m;
5163  m = 0;
5164  }
5165  if (m < 1.0) {
5166  m = 0;
5167  }
5168 
5169  /* convert the number */
5170  while (n > NK_FLOAT_PRECISION || m >= 0) {
5171  double weight = nk_pow(10.0, m);
5172  if (weight > 0) {
5173  double t = (double)n / weight;
5174  digit = nk_ifloord(t);
5175  n -= ((double)digit * weight);
5176  *(c++) = (char)('0' + (char)digit);
5177  }
5178  if (m == 0 && n > 0)
5179  *(c++) = '.';
5180  m--;
5181  }
5182 
5183  if (useExp) {
5184  /* convert the exponent */
5185  int i, j;
5186  *(c++) = 'e';
5187  if (m1 > 0) {
5188  *(c++) = '+';
5189  } else {
5190  *(c++) = '-';
5191  m1 = -m1;
5192  }
5193  m = 0;
5194  while (m1 > 0) {
5195  *(c++) = (char)('0' + (char)(m1 % 10));
5196  m1 /= 10;
5197  m++;
5198  }
5199  c -= m;
5200  for (i = 0, j = m-1; i<j; i++, j--) {
5201  /* swap without temporary */
5202  c[i] ^= c[j];
5203  c[j] ^= c[i];
5204  c[i] ^= c[j];
5205  }
5206  c += m;
5207  }
5208  *(c) = '\0';
5209  return s;
5210 }
5211 
5212 #ifdef NK_INCLUDE_STANDARD_VARARGS
5213 #ifndef NK_INCLUDE_STANDARD_IO
5214 static int
5215 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
5216 {
5217  enum nk_arg_type {
5218  NK_ARG_TYPE_CHAR,
5219  NK_ARG_TYPE_SHORT,
5220  NK_ARG_TYPE_DEFAULT,
5221  NK_ARG_TYPE_LONG
5222  };
5223  enum nk_arg_flags {
5224  NK_ARG_FLAG_LEFT = 0x01,
5225  NK_ARG_FLAG_PLUS = 0x02,
5226  NK_ARG_FLAG_SPACE = 0x04,
5227  NK_ARG_FLAG_NUM = 0x10,
5228  NK_ARG_FLAG_ZERO = 0x20
5229  };
5230 
5231  char number_buffer[NK_MAX_NUMBER_BUFFER];
5232  enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
5233  int precision = NK_DEFAULT;
5234  int width = NK_DEFAULT;
5235  nk_flags flag = 0;
5236 
5237  int len = 0;
5238  int result = -1;
5239  const char *iter = fmt;
5240 
5241  NK_ASSERT(buf);
5242  NK_ASSERT(buf_size);
5243  if (!buf || !buf_size || !fmt) return 0;
5244  for (iter = fmt; *iter && len < buf_size; iter++) {
5245  /* copy all non-format characters */
5246  while (*iter && (*iter != '%') && (len < buf_size))
5247  buf[len++] = *iter++;
5248  if (!(*iter) || len >= buf_size) break;
5249  iter++;
5250 
5251  /* flag arguments */
5252  while (*iter) {
5253  if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
5254  else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
5255  else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
5256  else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
5257  else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
5258  else break;
5259  iter++;
5260  }
5261 
5262  /* width argument */
5263  width = NK_DEFAULT;
5264  if (*iter >= '1' && *iter <= '9') {
5265  const char *end;
5266  width = nk_strtoi(iter, &end);
5267  if (end == iter)
5268  width = -1;
5269  else iter = end;
5270  } else if (*iter == '*') {
5271  width = va_arg(args, int);
5272  iter++;
5273  }
5274 
5275  /* precision argument */
5276  precision = NK_DEFAULT;
5277  if (*iter == '.') {
5278  iter++;
5279  if (*iter == '*') {
5280  precision = va_arg(args, int);
5281  iter++;
5282  } else {
5283  const char *end;
5284  precision = nk_strtoi(iter, &end);
5285  if (end == iter)
5286  precision = -1;
5287  else iter = end;
5288  }
5289  }
5290 
5291  /* length modifier */
5292  if (*iter == 'h') {
5293  if (*(iter+1) == 'h') {
5294  arg_type = NK_ARG_TYPE_CHAR;
5295  iter++;
5296  } else arg_type = NK_ARG_TYPE_SHORT;
5297  iter++;
5298  } else if (*iter == 'l') {
5299  arg_type = NK_ARG_TYPE_LONG;
5300  iter++;
5301  } else arg_type = NK_ARG_TYPE_DEFAULT;
5302 
5303  /* specifier */
5304  if (*iter == '%') {
5305  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5306  NK_ASSERT(precision == NK_DEFAULT);
5307  NK_ASSERT(width == NK_DEFAULT);
5308  if (len < buf_size)
5309  buf[len++] = '%';
5310  } else if (*iter == 's') {
5311  /* string */
5312  const char *str = va_arg(args, const char*);
5313  NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
5314  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5315  NK_ASSERT(precision == NK_DEFAULT);
5316  NK_ASSERT(width == NK_DEFAULT);
5317  if (str == buf) return -1;
5318  while (str && *str && len < buf_size)
5319  buf[len++] = *str++;
5320  } else if (*iter == 'n') {
5321  /* current length callback */
5322  signed int *n = va_arg(args, int*);
5323  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5324  NK_ASSERT(precision == NK_DEFAULT);
5325  NK_ASSERT(width == NK_DEFAULT);
5326  if (n) *n = len;
5327  } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
5328  /* signed integer */
5329  long value = 0;
5330  const char *num_iter;
5331  int num_len, num_print, padding;
5332  int cur_precision = NK_MAX(precision, 1);
5333  int cur_width = NK_MAX(width, 0);
5334 
5335  /* retrieve correct value type */
5336  if (arg_type == NK_ARG_TYPE_CHAR)
5337  value = (signed char)va_arg(args, int);
5338  else if (arg_type == NK_ARG_TYPE_SHORT)
5339  value = (signed short)va_arg(args, int);
5340  else if (arg_type == NK_ARG_TYPE_LONG)
5341  value = va_arg(args, signed long);
5342  else if (*iter == 'c')
5343  value = (unsigned char)va_arg(args, int);
5344  else value = va_arg(args, signed int);
5345 
5346  /* convert number to string */
5347  nk_itoa(number_buffer, value);
5348  num_len = nk_strlen(number_buffer);
5349  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5350  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5351  padding = NK_MAX(padding-1, 0);
5352 
5353  /* fill left padding up to a total of `width` characters */
5354  if (!(flag & NK_ARG_FLAG_LEFT)) {
5355  while (padding-- > 0 && (len < buf_size)) {
5356  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5357  buf[len++] = '0';
5358  else buf[len++] = ' ';
5359  }
5360  }
5361 
5362  /* copy string value representation into buffer */
5363  if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
5364  buf[len++] = '+';
5365  else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
5366  buf[len++] = ' ';
5367 
5368  /* fill up to precision number of digits with '0' */
5369  num_print = NK_MAX(cur_precision, num_len);
5370  while (precision && (num_print > num_len) && (len < buf_size)) {
5371  buf[len++] = '0';
5372  num_print--;
5373  }
5374 
5375  /* copy string value representation into buffer */
5376  num_iter = number_buffer;
5377  while (precision && *num_iter && len < buf_size)
5378  buf[len++] = *num_iter++;
5379 
5380  /* fill right padding up to width characters */
5381  if (flag & NK_ARG_FLAG_LEFT) {
5382  while ((padding-- > 0) && (len < buf_size))
5383  buf[len++] = ' ';
5384  }
5385  } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
5386  /* unsigned integer */
5387  unsigned long value = 0;
5388  int num_len = 0, num_print, padding = 0;
5389  int cur_precision = NK_MAX(precision, 1);
5390  int cur_width = NK_MAX(width, 0);
5391  unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
5392 
5393  /* print oct/hex/dec value */
5394  const char *upper_output_format = "0123456789ABCDEF";
5395  const char *lower_output_format = "0123456789abcdef";
5396  const char *output_format = (*iter == 'x') ?
5397  lower_output_format: upper_output_format;
5398 
5399  /* retrieve correct value type */
5400  if (arg_type == NK_ARG_TYPE_CHAR)
5401  value = (unsigned char)va_arg(args, int);
5402  else if (arg_type == NK_ARG_TYPE_SHORT)
5403  value = (unsigned short)va_arg(args, int);
5404  else if (arg_type == NK_ARG_TYPE_LONG)
5405  value = va_arg(args, unsigned long);
5406  else value = va_arg(args, unsigned int);
5407 
5408  do {
5409  /* convert decimal number into hex/oct number */
5410  int digit = output_format[value % base];
5411  if (num_len < NK_MAX_NUMBER_BUFFER)
5412  number_buffer[num_len++] = (char)digit;
5413  value /= base;
5414  } while (value > 0);
5415 
5416  num_print = NK_MAX(cur_precision, num_len);
5417  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5418  if (flag & NK_ARG_FLAG_NUM)
5419  padding = NK_MAX(padding-1, 0);
5420 
5421  /* fill left padding up to a total of `width` characters */
5422  if (!(flag & NK_ARG_FLAG_LEFT)) {
5423  while ((padding-- > 0) && (len < buf_size)) {
5424  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5425  buf[len++] = '0';
5426  else buf[len++] = ' ';
5427  }
5428  }
5429 
5430  /* fill up to precision number of digits */
5431  if (num_print && (flag & NK_ARG_FLAG_NUM)) {
5432  if ((*iter == 'o') && (len < buf_size)) {
5433  buf[len++] = '0';
5434  } else if ((*iter == 'x') && ((len+1) < buf_size)) {
5435  buf[len++] = '0';
5436  buf[len++] = 'x';
5437  } else if ((*iter == 'X') && ((len+1) < buf_size)) {
5438  buf[len++] = '0';
5439  buf[len++] = 'X';
5440  }
5441  }
5442  while (precision && (num_print > num_len) && (len < buf_size)) {
5443  buf[len++] = '0';
5444  num_print--;
5445  }
5446 
5447  /* reverse number direction */
5448  while (num_len > 0) {
5449  if (precision && (len < buf_size))
5450  buf[len++] = number_buffer[num_len-1];
5451  num_len--;
5452  }
5453 
5454  /* fill right padding up to width characters */
5455  if (flag & NK_ARG_FLAG_LEFT) {
5456  while ((padding-- > 0) && (len < buf_size))
5457  buf[len++] = ' ';
5458  }
5459  } else if (*iter == 'f') {
5460  /* floating point */
5461  const char *num_iter;
5462  int cur_precision = (precision < 0) ? 6: precision;
5463  int prefix, cur_width = NK_MAX(width, 0);
5464  double value = va_arg(args, double);
5465  int num_len = 0, frac_len = 0, dot = 0;
5466  int padding = 0;
5467 
5468  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5469  NK_DTOA(number_buffer, value);
5470  num_len = nk_strlen(number_buffer);
5471 
5472  /* calculate padding */
5473  num_iter = number_buffer;
5474  while (*num_iter && *num_iter != '.')
5475  num_iter++;
5476 
5477  prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
5478  padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
5479  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5480  padding = NK_MAX(padding-1, 0);
5481 
5482  /* fill left padding up to a total of `width` characters */
5483  if (!(flag & NK_ARG_FLAG_LEFT)) {
5484  while (padding-- > 0 && (len < buf_size)) {
5485  if (flag & NK_ARG_FLAG_ZERO)
5486  buf[len++] = '0';
5487  else buf[len++] = ' ';
5488  }
5489  }
5490 
5491  /* copy string value representation into buffer */
5492  num_iter = number_buffer;
5493  if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
5494  buf[len++] = '+';
5495  else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
5496  buf[len++] = ' ';
5497  while (*num_iter) {
5498  if (dot) frac_len++;
5499  if (len < buf_size)
5500  buf[len++] = *num_iter;
5501  if (*num_iter == '.') dot = 1;
5502  if (frac_len >= cur_precision) break;
5503  num_iter++;
5504  }
5505 
5506  /* fill number up to precision */
5507  while (frac_len < cur_precision) {
5508  if (!dot && len < buf_size) {
5509  buf[len++] = '.';
5510  dot = 1;
5511  }
5512  if (len < buf_size)
5513  buf[len++] = '0';
5514  frac_len++;
5515  }
5516 
5517  /* fill right padding up to width characters */
5518  if (flag & NK_ARG_FLAG_LEFT) {
5519  while ((padding-- > 0) && (len < buf_size))
5520  buf[len++] = ' ';
5521  }
5522  } else {
5523  /* Specifier not supported: g,G,e,E,p,z */
5524  NK_ASSERT(0 && "specifier is not supported!");
5525  return result;
5526  }
5527  }
5528  buf[(len >= buf_size)?(buf_size-1):len] = 0;
5529  result = (len >= buf_size)?-1:len;
5530  return result;
5531 }
5532 #endif
5533 
5534 NK_INTERN int
5535 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
5536 {
5537  int result = -1;
5538  NK_ASSERT(buf);
5539  NK_ASSERT(buf_size);
5540  if (!buf || !buf_size || !fmt) return 0;
5541 #ifdef NK_INCLUDE_STANDARD_IO
5542  result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
5543  result = (result >= buf_size) ? -1: result;
5544  buf[buf_size-1] = 0;
5545 #else
5546  result = nk_vsnprintf(buf, buf_size, fmt, args);
5547 #endif
5548  return result;
5549 }
5550 #endif
5551 
5552 NK_API nk_hash
5553 nk_murmur_hash(const void * key, int len, nk_hash seed)
5554 {
5555  /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
5556  #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
5557  union {const nk_uint *i; const nk_byte *b;} conv = {0};
5558  const nk_byte *data = (const nk_byte*)key;
5559  const int nblocks = len/4;
5560  nk_uint h1 = seed;
5561  const nk_uint c1 = 0xcc9e2d51;
5562  const nk_uint c2 = 0x1b873593;
5563  const nk_byte *tail;
5564  const nk_uint *blocks;
5565  nk_uint k1;
5566  int i;
5567 
5568  /* body */
5569  if (!key) return 0;
5570  conv.b = (data + nblocks*4);
5571  blocks = (const nk_uint*)conv.i;
5572  for (i = -nblocks; i; ++i) {
5573  k1 = blocks[i];
5574  k1 *= c1;
5575  k1 = NK_ROTL(k1,15);
5576  k1 *= c2;
5577 
5578  h1 ^= k1;
5579  h1 = NK_ROTL(h1,13);
5580  h1 = h1*5+0xe6546b64;
5581  }
5582 
5583  /* tail */
5584  tail = (const nk_byte*)(data + nblocks*4);
5585  k1 = 0;
5586  switch (len & 3) {
5587  case 3: k1 ^= (nk_uint)(tail[2] << 16);
5588  case 2: k1 ^= (nk_uint)(tail[1] << 8u);
5589  case 1: k1 ^= tail[0];
5590  k1 *= c1;
5591  k1 = NK_ROTL(k1,15);
5592  k1 *= c2;
5593  h1 ^= k1;
5594  default: break;
5595  }
5596 
5597  /* finalization */
5598  h1 ^= (nk_uint)len;
5599  /* fmix32 */
5600  h1 ^= h1 >> 16;
5601  h1 *= 0x85ebca6b;
5602  h1 ^= h1 >> 13;
5603  h1 *= 0xc2b2ae35;
5604  h1 ^= h1 >> 16;
5605 
5606  #undef NK_ROTL
5607  return h1;
5608 }
5609 
5610 #ifdef NK_INCLUDE_STANDARD_IO
5611 NK_INTERN char*
5612 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
5613 {
5614  char *buf;
5615  FILE *fd;
5616  long ret;
5617 
5618  NK_ASSERT(path);
5619  NK_ASSERT(siz);
5620  NK_ASSERT(alloc);
5621  if (!path || !siz || !alloc)
5622  return 0;
5623 
5624  fd = fopen(path, "rb");
5625  if (!fd) return 0;
5626  fseek(fd, 0, SEEK_END);
5627  ret = ftell(fd);
5628  if (ret < 0) {
5629  fclose(fd);
5630  return 0;
5631  }
5632  *siz = (nk_size)ret;
5633  fseek(fd, 0, SEEK_SET);
5634  buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
5635  NK_ASSERT(buf);
5636  if (!buf) {
5637  fclose(fd);
5638  return 0;
5639  }
5640  *siz = (nk_size)fread(buf, *siz, 1, fd);
5641  fclose(fd);
5642  return buf;
5643 }
5644 #endif
5645 
5646 /*
5647  * ==============================================================
5648  *
5649  * COLOR
5650  *
5651  * ===============================================================
5652  */
5653 NK_INTERN int
5654 nk_parse_hex(const char *p, int length)
5655 {
5656  int i = 0;
5657  int len = 0;
5658  while (len < length) {
5659  i <<= 4;
5660  if (p[len] >= 'a' && p[len] <= 'f')
5661  i += ((p[len] - 'a') + 10);
5662  else if (p[len] >= 'A' && p[len] <= 'F')
5663  i += ((p[len] - 'A') + 10);
5664  else i += (p[len] - '0');
5665  len++;
5666  }
5667  return i;
5668 }
5669 
5670 NK_API struct nk_color
5671 nk_rgba(int r, int g, int b, int a)
5672 {
5673  struct nk_color ret;
5674  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5675  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5676  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5677  ret.a = (nk_byte)NK_CLAMP(0, a, 255);
5678  return ret;
5679 }
5680 
5681 NK_API struct nk_color
5682 nk_rgb_hex(const char *rgb)
5683 {
5684  struct nk_color col;
5685  const char *c = rgb;
5686  if (*c == '#') c++;
5687  col.r = (nk_byte)nk_parse_hex(c, 2);
5688  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5689  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5690  col.a = 255;
5691  return col;
5692 }
5693 
5694 NK_API struct nk_color
5695 nk_rgba_hex(const char *rgb)
5696 {
5697  struct nk_color col;
5698  const char *c = rgb;
5699  if (*c == '#') c++;
5700  col.r = (nk_byte)nk_parse_hex(c, 2);
5701  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5702  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5703  col.a = (nk_byte)nk_parse_hex(c+6, 2);
5704  return col;
5705 }
5706 
5707 NK_API void
5708 nk_color_hex_rgba(char *output, struct nk_color col)
5709 {
5710  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5711  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5712  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5713  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5714  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5715  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5716  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5717  output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
5718  output[7] = (char)NK_TO_HEX((col.a & 0x0F));
5719  output[8] = '\0';
5720  #undef NK_TO_HEX
5721 }
5722 
5723 NK_API void
5724 nk_color_hex_rgb(char *output, struct nk_color col)
5725 {
5726  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5727  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5728  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5729  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5730  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5731  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5732  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5733  output[6] = '\0';
5734  #undef NK_TO_HEX
5735 }
5736 
5737 NK_API struct nk_color
5738 nk_rgba_iv(const int *c)
5739 {
5740  return nk_rgba(c[0], c[1], c[2], c[3]);
5741 }
5742 
5743 NK_API struct nk_color
5744 nk_rgba_bv(const nk_byte *c)
5745 {
5746  return nk_rgba(c[0], c[1], c[2], c[3]);
5747 }
5748 
5749 NK_API struct nk_color
5750 nk_rgb(int r, int g, int b)
5751 {
5752  struct nk_color ret;
5753  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5754  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5755  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5756  ret.a = (nk_byte)255;
5757  return ret;
5758 }
5759 
5760 NK_API struct nk_color
5761 nk_rgb_iv(const int *c)
5762 {
5763  return nk_rgb(c[0], c[1], c[2]);
5764 }
5765 
5766 NK_API struct nk_color
5767 nk_rgb_bv(const nk_byte* c)
5768 {
5769  return nk_rgb(c[0], c[1], c[2]);
5770 }
5771 
5772 NK_API struct nk_color
5773 nk_rgba_u32(nk_uint in)
5774 {
5775  struct nk_color ret;
5776  ret.r = (in & 0xFF);
5777  ret.g = ((in >> 8) & 0xFF);
5778  ret.b = ((in >> 16) & 0xFF);
5779  ret.a = (nk_byte)((in >> 24) & 0xFF);
5780  return ret;
5781 }
5782 
5783 NK_API struct nk_color
5784 nk_rgba_f(float r, float g, float b, float a)
5785 {
5786  struct nk_color ret;
5787  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5788  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5789  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5790  ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
5791  return ret;
5792 }
5793 
5794 NK_API struct nk_color
5795 nk_rgba_fv(const float *c)
5796 {
5797  return nk_rgba_f(c[0], c[1], c[2], c[3]);
5798 }
5799 
5800 NK_API struct nk_color
5801 nk_rgb_f(float r, float g, float b)
5802 {
5803  struct nk_color ret;
5804  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5805  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5806  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5807  ret.a = 255;
5808  return ret;
5809 }
5810 
5811 NK_API struct nk_color
5812 nk_rgb_fv(const float *c)
5813 {
5814  return nk_rgb_f(c[0], c[1], c[2]);
5815 }
5816 
5817 NK_API struct nk_color
5818 nk_hsv(int h, int s, int v)
5819 {
5820  return nk_hsva(h, s, v, 255);
5821 }
5822 
5823 NK_API struct nk_color
5824 nk_hsv_iv(const int *c)
5825 {
5826  return nk_hsv(c[0], c[1], c[2]);
5827 }
5828 
5829 NK_API struct nk_color
5830 nk_hsv_bv(const nk_byte *c)
5831 {
5832  return nk_hsv(c[0], c[1], c[2]);
5833 }
5834 
5835 NK_API struct nk_color
5836 nk_hsv_f(float h, float s, float v)
5837 {
5838  return nk_hsva_f(h, s, v, 1.0f);
5839 }
5840 
5841 NK_API struct nk_color
5842 nk_hsv_fv(const float *c)
5843 {
5844  return nk_hsv_f(c[0], c[1], c[2]);
5845 }
5846 
5847 NK_API struct nk_color
5848 nk_hsva(int h, int s, int v, int a)
5849 {
5850  float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
5851  float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
5852  float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
5853  float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
5854  return nk_hsva_f(hf, sf, vf, af);
5855 }
5856 
5857 NK_API struct nk_color
5858 nk_hsva_iv(const int *c)
5859 {
5860  return nk_hsva(c[0], c[1], c[2], c[3]);
5861 }
5862 
5863 NK_API struct nk_color
5864 nk_hsva_bv(const nk_byte *c)
5865 {
5866  return nk_hsva(c[0], c[1], c[2], c[3]);
5867 }
5868 
5869 NK_API struct nk_color
5870 nk_hsva_f(float h, float s, float v, float a)
5871 {
5872  struct nk_colorf out = {0,0,0,0};
5873  float p, q, t, f;
5874  int i;
5875 
5876  if (s <= 0.0f) {
5877  out.r = v; out.g = v; out.b = v;
5878  return nk_rgb_f(out.r, out.g, out.b);
5879  }
5880 
5881  h = h / (60.0f/360.0f);
5882  i = (int)h;
5883  f = h - (float)i;
5884  p = v * (1.0f - s);
5885  q = v * (1.0f - (s * f));
5886  t = v * (1.0f - s * (1.0f - f));
5887 
5888  switch (i) {
5889  case 0: default: out.r = v; out.g = t; out.b = p; break;
5890  case 1: out.r = q; out.g = v; out.b = p; break;
5891  case 2: out.r = p; out.g = v; out.b = t; break;
5892  case 3: out.r = p; out.g = q; out.b = v; break;
5893  case 4: out.r = t; out.g = p; out.b = v; break;
5894  case 5: out.r = v; out.g = p; out.b = q; break;
5895  }
5896  return nk_rgba_f(out.r, out.g, out.b, a);
5897 }
5898 
5899 NK_API struct nk_color
5900 nk_hsva_fv(const float *c)
5901 {
5902  return nk_hsva_f(c[0], c[1], c[2], c[3]);
5903 }
5904 
5905 NK_API nk_uint
5906 nk_color_u32(struct nk_color in)
5907 {
5908  nk_uint out = (nk_uint)in.r;
5909  out |= ((nk_uint)in.g << 8);
5910  out |= ((nk_uint)in.b << 16);
5911  out |= ((nk_uint)in.a << 24);
5912  return out;
5913 }
5914 
5915 NK_API void
5916 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
5917 {
5918  NK_STORAGE const float s = 1.0f/255.0f;
5919  *r = (float)in.r * s;
5920  *g = (float)in.g * s;
5921  *b = (float)in.b * s;
5922  *a = (float)in.a * s;
5923 }
5924 
5925 NK_API void
5926 nk_color_fv(float *c, struct nk_color in)
5927 {
5928  nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
5929 }
5930 
5931 NK_API void
5932 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
5933 {
5934  NK_STORAGE const double s = 1.0/255.0;
5935  *r = (double)in.r * s;
5936  *g = (double)in.g * s;
5937  *b = (double)in.b * s;
5938  *a = (double)in.a * s;
5939 }
5940 
5941 NK_API void
5942 nk_color_dv(double *c, struct nk_color in)
5943 {
5944  nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
5945 }
5946 
5947 NK_API void
5948 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
5949 {
5950  float a;
5951  nk_color_hsva_f(out_h, out_s, out_v, &a, in);
5952 }
5953 
5954 NK_API void
5955 nk_color_hsv_fv(float *out, struct nk_color in)
5956 {
5957  float a;
5958  nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
5959 }
5960 
5961 NK_API void
5962 nk_color_hsva_f(float *out_h, float *out_s,
5963  float *out_v, float *out_a, struct nk_color in)
5964 {
5965  float chroma;
5966  float K = 0.0f;
5967  float r,g,b,a;
5968 
5969  nk_color_f(&r,&g,&b,&a, in);
5970  if (g < b) {
5971  const float t = g; g = b; b = t;
5972  K = -1.f;
5973  }
5974  if (r < g) {
5975  const float t = r; r = g; g = t;
5976  K = -2.f/6.0f - K;
5977  }
5978  chroma = r - ((g < b) ? g: b);
5979  *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f));
5980  *out_s = chroma / (r + 1e-20f);
5981  *out_v = r;
5982  *out_a = (float)in.a / 255.0f;
5983 }
5984 
5985 NK_API void
5986 nk_color_hsva_fv(float *out, struct nk_color in)
5987 {
5988  nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
5989 }
5990 
5991 NK_API void
5992 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
5993  int *out_a, struct nk_color in)
5994 {
5995  float h,s,v,a;
5996  nk_color_hsva_f(&h, &s, &v, &a, in);
5997  *out_h = (nk_byte)(h * 255.0f);
5998  *out_s = (nk_byte)(s * 255.0f);
5999  *out_v = (nk_byte)(v * 255.0f);
6000  *out_a = (nk_byte)(a * 255.0f);
6001 }
6002 
6003 NK_API void
6004 nk_color_hsva_iv(int *out, struct nk_color in)
6005 {
6006  nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
6007 }
6008 
6009 NK_API void
6010 nk_color_hsva_bv(nk_byte *out, struct nk_color in)
6011 {
6012  int tmp[4];
6013  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6014  out[0] = (nk_byte)tmp[0];
6015  out[1] = (nk_byte)tmp[1];
6016  out[2] = (nk_byte)tmp[2];
6017  out[3] = (nk_byte)tmp[3];
6018 }
6019 
6020 NK_API void
6021 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in)
6022 {
6023  int tmp[4];
6024  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6025  *h = (nk_byte)tmp[0];
6026  *s = (nk_byte)tmp[1];
6027  *v = (nk_byte)tmp[2];
6028  *a = (nk_byte)tmp[3];
6029 }
6030 
6031 NK_API void
6032 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
6033 {
6034  int a;
6035  nk_color_hsva_i(out_h, out_s, out_v, &a, in);
6036 }
6037 
6038 NK_API void
6039 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
6040 {
6041  int tmp[4];
6042  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6043  *out_h = (nk_byte)tmp[0];
6044  *out_s = (nk_byte)tmp[1];
6045  *out_v = (nk_byte)tmp[2];
6046 }
6047 
6048 NK_API void
6049 nk_color_hsv_iv(int *out, struct nk_color in)
6050 {
6051  nk_color_hsv_i(&out[0], &out[1], &out[2], in);
6052 }
6053 
6054 NK_API void
6055 nk_color_hsv_bv(nk_byte *out, struct nk_color in)
6056 {
6057  int tmp[4];
6058  nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
6059  out[0] = (nk_byte)tmp[0];
6060  out[1] = (nk_byte)tmp[1];
6061  out[2] = (nk_byte)tmp[2];
6062 }
6063 /*
6064  * ==============================================================
6065  *
6066  * IMAGE
6067  *
6068  * ===============================================================
6069  */
6070 NK_API nk_handle
6071 nk_handle_ptr(void *ptr)
6072 {
6073  nk_handle handle = {0};
6074  handle.ptr = ptr;
6075  return handle;
6076 }
6077 
6078 NK_API nk_handle
6079 nk_handle_id(int id)
6080 {
6081  nk_handle handle;
6082  nk_zero_struct(handle);
6083  handle.id = id;
6084  return handle;
6085 }
6086 
6087 NK_API struct nk_image
6088 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
6089 {
6090  struct nk_image s;
6091  nk_zero(&s, sizeof(s));
6092  s.handle.ptr = ptr;
6093  s.w = w; s.h = h;
6094  s.region[0] = (unsigned short)r.x;
6095  s.region[1] = (unsigned short)r.y;
6096  s.region[2] = (unsigned short)r.w;
6097  s.region[3] = (unsigned short)r.h;
6098  return s;
6099 }
6100 
6101 NK_API struct nk_image
6102 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
6103 {
6104  struct nk_image s;
6105  nk_zero(&s, sizeof(s));
6106  s.handle.id = id;
6107  s.w = w; s.h = h;
6108  s.region[0] = (unsigned short)r.x;
6109  s.region[1] = (unsigned short)r.y;
6110  s.region[2] = (unsigned short)r.w;
6111  s.region[3] = (unsigned short)r.h;
6112  return s;
6113 }
6114 
6115 NK_API struct nk_image
6116 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
6117  struct nk_rect r)
6118 {
6119  struct nk_image s;
6120  nk_zero(&s, sizeof(s));
6121  s.handle = handle;
6122  s.w = w; s.h = h;
6123  s.region[0] = (unsigned short)r.x;
6124  s.region[1] = (unsigned short)r.y;
6125  s.region[2] = (unsigned short)r.w;
6126  s.region[3] = (unsigned short)r.h;
6127  return s;
6128 }
6129 
6130 NK_API struct nk_image
6131 nk_image_handle(nk_handle handle)
6132 {
6133  struct nk_image s;
6134  nk_zero(&s, sizeof(s));
6135  s.handle = handle;
6136  s.w = 0; s.h = 0;
6137  s.region[0] = 0;
6138  s.region[1] = 0;
6139  s.region[2] = 0;
6140  s.region[3] = 0;
6141  return s;
6142 }
6143 
6144 NK_API struct nk_image
6145 nk_image_ptr(void *ptr)
6146 {
6147  struct nk_image s;
6148  nk_zero(&s, sizeof(s));
6149  NK_ASSERT(ptr);
6150  s.handle.ptr = ptr;
6151  s.w = 0; s.h = 0;
6152  s.region[0] = 0;
6153  s.region[1] = 0;
6154  s.region[2] = 0;
6155  s.region[3] = 0;
6156  return s;
6157 }
6158 
6159 NK_API struct nk_image
6160 nk_image_id(int id)
6161 {
6162  struct nk_image s;
6163  nk_zero(&s, sizeof(s));
6164  s.handle.id = id;
6165  s.w = 0; s.h = 0;
6166  s.region[0] = 0;
6167  s.region[1] = 0;
6168  s.region[2] = 0;
6169  s.region[3] = 0;
6170  return s;
6171 }
6172 
6173 NK_API int
6174 nk_image_is_subimage(const struct nk_image* img)
6175 {
6176  NK_ASSERT(img);
6177  return !(img->w == 0 && img->h == 0);
6178 }
6179 
6180 NK_INTERN void
6181 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6182  float x1, float y1)
6183 {
6184  NK_ASSERT(a);
6185  NK_ASSERT(clip);
6186  clip->x = NK_MAX(a->x, x0);
6187  clip->y = NK_MAX(a->y, y0);
6188  clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6189  clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6190  clip->w = NK_MAX(0, clip->w);
6191  clip->h = NK_MAX(0, clip->h);
6192 }
6193 
6194 NK_API void
6195 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r,
6196  float pad_x, float pad_y, enum nk_heading direction)
6197 {
6198  float w_half, h_half;
6199  NK_ASSERT(result);
6200 
6201  r.w = NK_MAX(2 * pad_x, r.w);
6202  r.h = NK_MAX(2 * pad_y, r.h);
6203  r.w = r.w - 2 * pad_x;
6204  r.h = r.h - 2 * pad_y;
6205 
6206  r.x = r.x + pad_x;
6207  r.y = r.y + pad_y;
6208 
6209  w_half = r.w / 2.0f;
6210  h_half = r.h / 2.0f;
6211 
6212  if (direction == NK_UP) {
6213  result[0] = nk_vec2(r.x + w_half, r.y);
6214  result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6215  result[2] = nk_vec2(r.x, r.y + r.h);
6216  } else if (direction == NK_RIGHT) {
6217  result[0] = nk_vec2(r.x, r.y);
6218  result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6219  result[2] = nk_vec2(r.x, r.y + r.h);
6220  } else if (direction == NK_DOWN) {
6221  result[0] = nk_vec2(r.x, r.y);
6222  result[1] = nk_vec2(r.x + r.w, r.y);
6223  result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6224  } else {
6225  result[0] = nk_vec2(r.x, r.y + h_half);
6226  result[1] = nk_vec2(r.x + r.w, r.y);
6227  result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6228  }
6229 }
6230 
6231 NK_INTERN int
6232 nk_text_clamp(const struct nk_user_font *font, const char *text,
6233  int text_len, float space, int *glyphs, float *text_width,
6234  nk_rune *sep_list, int sep_count)
6235 {
6236  int i = 0;
6237  int glyph_len = 0;
6238  float last_width = 0;
6239  nk_rune unicode = 0;
6240  float width = 0;
6241  int len = 0;
6242  int g = 0;
6243  float s;
6244 
6245  int sep_len = 0;
6246  int sep_g = 0;
6247  float sep_width = 0;
6248  sep_count = NK_MAX(sep_count,0);
6249 
6250  glyph_len = nk_utf_decode(text, &unicode, text_len);
6251  while (glyph_len && (width < space) && (len < text_len)) {
6252  len += glyph_len;
6253  s = font->width(font->userdata, font->height, text, len);
6254  for (i = 0; i < sep_count; ++i) {
6255  if (unicode != sep_list[i]) continue;
6256  sep_width = last_width = width;
6257  sep_g = g+1;
6258  sep_len = len;
6259  break;
6260  }
6261  if (i == sep_count){
6262  last_width = sep_width = width;
6263  sep_g = g+1;
6264  }
6265  width = s;
6266  glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
6267  g++;
6268  }
6269  if (len >= text_len) {
6270  *glyphs = g;
6271  *text_width = last_width;
6272  return len;
6273  } else {
6274  *glyphs = sep_g;
6275  *text_width = sep_width;
6276  return (!sep_len) ? len: sep_len;
6277  }
6278 }
6279 
6280 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
6281 NK_INTERN struct nk_vec2
6282 nk_text_calculate_text_bounds(const struct nk_user_font *font,
6283  const char *begin, int byte_len, float row_height, const char **remaining,
6284  struct nk_vec2 *out_offset, int *glyphs, int op)
6285 {
6286  float line_height = row_height;
6287  struct nk_vec2 text_size = nk_vec2(0,0);
6288  float line_width = 0.0f;
6289 
6290  float glyph_width;
6291  int glyph_len = 0;
6292  nk_rune unicode = 0;
6293  int text_len = 0;
6294  if (!begin || byte_len <= 0 || !font)
6295  return nk_vec2(0,row_height);
6296 
6297  glyph_len = nk_utf_decode(begin, &unicode, byte_len);
6298  if (!glyph_len) return text_size;
6299  glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
6300 
6301  *glyphs = 0;
6302  while ((text_len < byte_len) && glyph_len) {
6303  if (unicode == '\n') {
6304  text_size.x = NK_MAX(text_size.x, line_width);
6305  text_size.y += line_height;
6306  line_width = 0;
6307  *glyphs+=1;
6308  if (op == NK_STOP_ON_NEW_LINE)
6309  break;
6310 
6311  text_len++;
6312  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6313  continue;
6314  }
6315 
6316  if (unicode == '\r') {
6317  text_len++;
6318  *glyphs+=1;
6319  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6320  continue;
6321  }
6322 
6323  *glyphs = *glyphs + 1;
6324  text_len += glyph_len;
6325  line_width += (float)glyph_width;
6326  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6327  glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
6328  continue;
6329  }
6330 
6331  if (text_size.x < line_width)
6332  text_size.x = line_width;
6333  if (out_offset)
6334  *out_offset = nk_vec2(line_width, text_size.y + line_height);
6335  if (line_width > 0 || text_size.y == 0.0f)
6336  text_size.y += line_height;
6337  if (remaining)
6338  *remaining = begin+text_len;
6339  return text_size;
6340 }
6341 
6342 /* ==============================================================
6343  *
6344  * UTF-8
6345  *
6346  * ===============================================================*/
6347 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
6348 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
6349 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
6350 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
6351 
6352 NK_INTERN int
6353 nk_utf_validate(nk_rune *u, int i)
6354 {
6355  NK_ASSERT(u);
6356  if (!u) return 0;
6357  if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
6358  NK_BETWEEN(*u, 0xD800, 0xDFFF))
6359  *u = NK_UTF_INVALID;
6360  for (i = 1; *u > nk_utfmax[i]; ++i);
6361  return i;
6362 }
6363 
6364 NK_INTERN nk_rune
6365 nk_utf_decode_byte(char c, int *i)
6366 {
6367  NK_ASSERT(i);
6368  if (!i) return 0;
6369  for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
6370  if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
6371  return (nk_byte)(c & ~nk_utfmask[*i]);
6372  }
6373  return 0;
6374 }
6375 
6376 NK_API int
6377 nk_utf_decode(const char *c, nk_rune *u, int clen)
6378 {
6379  int i, j, len, type=0;
6380  nk_rune udecoded;
6381 
6382  NK_ASSERT(c);
6383  NK_ASSERT(u);
6384 
6385  if (!c || !u) return 0;
6386  if (!clen) return 0;
6387  *u = NK_UTF_INVALID;
6388 
6389  udecoded = nk_utf_decode_byte(c[0], &len);
6390  if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
6391  return 1;
6392 
6393  for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
6394  udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
6395  if (type != 0)
6396  return j;
6397  }
6398  if (j < len)
6399  return 0;
6400  *u = udecoded;
6401  nk_utf_validate(u, len);
6402  return len;
6403 }
6404 
6405 NK_INTERN char
6406 nk_utf_encode_byte(nk_rune u, int i)
6407 {
6408  return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
6409 }
6410 
6411 NK_API int
6412 nk_utf_encode(nk_rune u, char *c, int clen)
6413 {
6414  int len, i;
6415  len = nk_utf_validate(&u, 0);
6416  if (clen < len || !len || len > NK_UTF_SIZE)
6417  return 0;
6418 
6419  for (i = len - 1; i != 0; --i) {
6420  c[i] = nk_utf_encode_byte(u, 0);
6421  u >>= 6;
6422  }
6423  c[0] = nk_utf_encode_byte(u, len);
6424  return len;
6425 }
6426 
6427 NK_API int
6428 nk_utf_len(const char *str, int len)
6429 {
6430  const char *text;
6431  int glyphs = 0;
6432  int text_len;
6433  int glyph_len;
6434  int src_len = 0;
6435  nk_rune unicode;
6436 
6437  NK_ASSERT(str);
6438  if (!str || !len) return 0;
6439 
6440  text = str;
6441  text_len = len;
6442  glyph_len = nk_utf_decode(text, &unicode, text_len);
6443  while (glyph_len && src_len < len) {
6444  glyphs++;
6445  src_len = src_len + glyph_len;
6446  glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
6447  }
6448  return glyphs;
6449 }
6450 
6451 NK_API const char*
6452 nk_utf_at(const char *buffer, int length, int index,
6453  nk_rune *unicode, int *len)
6454 {
6455  int i = 0;
6456  int src_len = 0;
6457  int glyph_len = 0;
6458  const char *text;
6459  int text_len;
6460 
6461  NK_ASSERT(buffer);
6462  NK_ASSERT(unicode);
6463  NK_ASSERT(len);
6464 
6465  if (!buffer || !unicode || !len) return 0;
6466  if (index < 0) {
6467  *unicode = NK_UTF_INVALID;
6468  *len = 0;
6469  return 0;
6470  }
6471 
6472  text = buffer;
6473  text_len = length;
6474  glyph_len = nk_utf_decode(text, unicode, text_len);
6475  while (glyph_len) {
6476  if (i == index) {
6477  *len = glyph_len;
6478  break;
6479  }
6480 
6481  i++;
6482  src_len = src_len + glyph_len;
6483  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
6484  }
6485  if (i != index) return 0;
6486  return buffer + src_len;
6487 }
6488 
6489 /* ==============================================================
6490  *
6491  * BUFFER
6492  *
6493  * ===============================================================*/
6494 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6495 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size)
6496 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);}
6497 NK_INTERN void nk_mfree(nk_handle unused, void *ptr)
6498 {NK_UNUSED(unused); free(ptr);}
6499 
6500 NK_API void
6501 nk_buffer_init_default(struct nk_buffer *buffer)
6502 {
6503  struct nk_allocator alloc;
6504  alloc.userdata.ptr = 0;
6505  alloc.alloc = nk_malloc;
6506  alloc.free = nk_mfree;
6507  nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
6508 }
6509 #endif
6510 
6511 NK_API void
6512 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
6513  nk_size initial_size)
6514 {
6515  NK_ASSERT(b);
6516  NK_ASSERT(a);
6517  NK_ASSERT(initial_size);
6518  if (!b || !a || !initial_size) return;
6519 
6520  nk_zero(b, sizeof(*b));
6521  b->type = NK_BUFFER_DYNAMIC;
6522  b->memory.ptr = a->alloc(a->userdata,0, initial_size);
6523  b->memory.size = initial_size;
6524  b->size = initial_size;
6525  b->grow_factor = 2.0f;
6526  b->pool = *a;
6527 }
6528 
6529 NK_API void
6530 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
6531 {
6532  NK_ASSERT(b);
6533  NK_ASSERT(m);
6534  NK_ASSERT(size);
6535  if (!b || !m || !size) return;
6536 
6537  nk_zero(b, sizeof(*b));
6538  b->type = NK_BUFFER_FIXED;
6539  b->memory.ptr = m;
6540  b->memory.size = size;
6541  b->size = size;
6542 }
6543 
6544 NK_INTERN void*
6545 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment,
6546  enum nk_buffer_allocation_type type)
6547 {
6548  void *memory = 0;
6549  switch (type) {
6550  default:
6551  case NK_BUFFER_MAX:
6552  case NK_BUFFER_FRONT:
6553  if (align) {
6554  memory = NK_ALIGN_PTR(unaligned, align);
6555  *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
6556  } else {
6557  memory = unaligned;
6558  *alignment = 0;
6559  }
6560  break;
6561  case NK_BUFFER_BACK:
6562  if (align) {
6563  memory = NK_ALIGN_PTR_BACK(unaligned, align);
6564  *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
6565  } else {
6566  memory = unaligned;
6567  *alignment = 0;
6568  }
6569  break;
6570  }
6571  return memory;
6572 }
6573 
6574 NK_INTERN void*
6575 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
6576 {
6577  void *temp;
6578  nk_size buffer_size;
6579 
6580  NK_ASSERT(b);
6581  NK_ASSERT(size);
6582  if (!b || !size || !b->pool.alloc || !b->pool.free)
6583  return 0;
6584 
6585  buffer_size = b->memory.size;
6586  temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
6587  NK_ASSERT(temp);
6588  if (!temp) return 0;
6589 
6590  *size = capacity;
6591  if (temp != b->memory.ptr) {
6592  NK_MEMCPY(temp, b->memory.ptr, buffer_size);
6593  b->pool.free(b->pool.userdata, b->memory.ptr);
6594  }
6595 
6596  if (b->size == buffer_size) {
6597  /* no back buffer so just set correct size */
6598  b->size = capacity;
6599  return temp;
6600  } else {
6601  /* copy back buffer to the end of the new buffer */
6602  void *dst, *src;
6603  nk_size back_size;
6604  back_size = buffer_size - b->size;
6605  dst = nk_ptr_add(void, temp, capacity - back_size);
6606  src = nk_ptr_add(void, temp, b->size);
6607  NK_MEMCPY(dst, src, back_size);
6608  b->size = capacity - back_size;
6609  }
6610  return temp;
6611 }
6612 
6613 NK_INTERN void*
6614 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
6615  nk_size size, nk_size align)
6616 {
6617  int full;
6618  nk_size alignment;
6619  void *unaligned;
6620  void *memory;
6621 
6622  NK_ASSERT(b);
6623  NK_ASSERT(size);
6624  if (!b || !size) return 0;
6625  b->needed += size;
6626 
6627  /* calculate total size with needed alignment + size */
6628  if (type == NK_BUFFER_FRONT)
6629  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6630  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6631  memory = nk_buffer_align(unaligned, align, &alignment, type);
6632 
6633  /* check if buffer has enough memory*/
6634  if (type == NK_BUFFER_FRONT)
6635  full = ((b->allocated + size + alignment) > b->size);
6636  else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
6637 
6638  if (full) {
6639  nk_size capacity;
6640  if (b->type != NK_BUFFER_DYNAMIC)
6641  return 0;
6642  NK_ASSERT(b->pool.alloc && b->pool.free);
6643  if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
6644  return 0;
6645 
6646  /* buffer is full so allocate bigger buffer if dynamic */
6647  capacity = (nk_size)((float)b->memory.size * b->grow_factor);
6648  capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
6649  b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
6650  if (!b->memory.ptr) return 0;
6651 
6652  /* align newly allocated pointer */
6653  if (type == NK_BUFFER_FRONT)
6654  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6655  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6656  memory = nk_buffer_align(unaligned, align, &alignment, type);
6657  }
6658  if (type == NK_BUFFER_FRONT)
6659  b->allocated += size + alignment;
6660  else b->size -= (size + alignment);
6661  b->needed += alignment;
6662  b->calls++;
6663  return memory;
6664 }
6665 
6666 NK_API void
6668  const void *memory, nk_size size, nk_size align)
6669 {
6670  void *mem = nk_buffer_alloc(b, type, size, align);
6671  if (!mem) return;
6672  NK_MEMCPY(mem, memory, size);
6673 }
6674 
6675 NK_API void
6676 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6677 {
6678  NK_ASSERT(buffer);
6679  if (!buffer) return;
6680  buffer->marker[type].active = nk_true;
6681  if (type == NK_BUFFER_BACK)
6682  buffer->marker[type].offset = buffer->size;
6683  else buffer->marker[type].offset = buffer->allocated;
6684 }
6685 
6686 NK_API void
6687 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type)
6688 {
6689  NK_ASSERT(buffer);
6690  if (!buffer) return;
6691  if (type == NK_BUFFER_BACK) {
6692  /* reset back buffer either back to marker or empty */
6693  buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
6694  if (buffer->marker[type].active)
6695  buffer->size = buffer->marker[type].offset;
6696  else buffer->size = buffer->memory.size;
6697  buffer->marker[type].active = nk_false;
6698  } else {
6699  /* reset front buffer either back to back marker or empty */
6700  buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
6701  if (buffer->marker[type].active)
6702  buffer->allocated = buffer->marker[type].offset;
6703  else buffer->allocated = 0;
6704  buffer->marker[type].active = nk_false;
6705  }
6706 }
6707 
6708 NK_API void
6709 nk_buffer_clear(struct nk_buffer *b)
6710 {
6711  NK_ASSERT(b);
6712  if (!b) return;
6713  b->allocated = 0;
6714  b->size = b->memory.size;
6715  b->calls = 0;
6716  b->needed = 0;
6717 }
6718 
6719 NK_API void
6720 nk_buffer_free(struct nk_buffer *b)
6721 {
6722  NK_ASSERT(b);
6723  if (!b || !b->memory.ptr) return;
6724  if (b->type == NK_BUFFER_FIXED) return;
6725  if (!b->pool.free) return;
6726  NK_ASSERT(b->pool.free);
6727  b->pool.free(b->pool.userdata, b->memory.ptr);
6728 }
6729 
6730 NK_API void
6731 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
6732 {
6733  NK_ASSERT(b);
6734  NK_ASSERT(s);
6735  if (!s || !b) return;
6736  s->allocated = b->allocated;
6737  s->size = b->memory.size;
6738  s->needed = b->needed;
6739  s->memory = b->memory.ptr;
6740  s->calls = b->calls;
6741 }
6742 
6743 NK_API void*
6744 nk_buffer_memory(struct nk_buffer *buffer)
6745 {
6746  NK_ASSERT(buffer);
6747  if (!buffer) return 0;
6748  return buffer->memory.ptr;
6749 }
6750 
6751 NK_API const void*
6752 nk_buffer_memory_const(const struct nk_buffer *buffer)
6753 {
6754  NK_ASSERT(buffer);
6755  if (!buffer) return 0;
6756  return buffer->memory.ptr;
6757 }
6758 
6759 NK_API nk_size
6760 nk_buffer_total(struct nk_buffer *buffer)
6761 {
6762  NK_ASSERT(buffer);
6763  if (!buffer) return 0;
6764  return buffer->memory.size;
6765 }
6766 
6767 /*
6768  * ==============================================================
6769  *
6770  * STRING
6771  *
6772  * ===============================================================
6773  */
6774 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6775 NK_API void
6776 nk_str_init_default(struct nk_str *str)
6777 {
6778  struct nk_allocator alloc;
6779  alloc.userdata.ptr = 0;
6780  alloc.alloc = nk_malloc;
6781  alloc.free = nk_mfree;
6782  nk_buffer_init(&str->buffer, &alloc, 32);
6783  str->len = 0;
6784 }
6785 #endif
6786 
6787 NK_API void
6788 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
6789 {
6790  nk_buffer_init(&str->buffer, alloc, size);
6791  str->len = 0;
6792 }
6793 
6794 NK_API void
6795 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
6796 {
6797  nk_buffer_init_fixed(&str->buffer, memory, size);
6798  str->len = 0;
6799 }
6800 
6801 NK_API int
6802 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
6803 {
6804  char *mem;
6805  NK_ASSERT(s);
6806  NK_ASSERT(str);
6807  if (!s || !str || !len) return 0;
6808  mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6809  if (!mem) return 0;
6810  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6811  s->len += nk_utf_len(str, len);
6812  return len;
6813 }
6814 
6815 NK_API int
6816 nk_str_append_str_char(struct nk_str *s, const char *str)
6817 {
6818  return nk_str_append_text_char(s, str, nk_strlen(str));
6819 }
6820 
6821 NK_API int
6822 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
6823 {
6824  int i = 0;
6825  int byte_len = 0;
6826  nk_rune unicode;
6827  if (!str || !text || !len) return 0;
6828  for (i = 0; i < len; ++i)
6829  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6830  nk_str_append_text_char(str, text, byte_len);
6831  return len;
6832 }
6833 
6834 NK_API int
6835 nk_str_append_str_utf8(struct nk_str *str, const char *text)
6836 {
6837  int runes = 0;
6838  int byte_len = 0;
6839  int num_runes = 0;
6840  int glyph_len = 0;
6841  nk_rune unicode;
6842  if (!str || !text) return 0;
6843 
6844  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6845  while (unicode != '\0' && glyph_len) {
6846  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6847  byte_len += glyph_len;
6848  num_runes++;
6849  }
6850  nk_str_append_text_char(str, text, byte_len);
6851  return runes;
6852 }
6853 
6854 NK_API int
6855 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
6856 {
6857  int i = 0;
6858  int byte_len = 0;
6859  nk_glyph glyph;
6860 
6861  NK_ASSERT(str);
6862  if (!str || !text || !len) return 0;
6863  for (i = 0; i < len; ++i) {
6864  byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
6865  if (!byte_len) break;
6866  nk_str_append_text_char(str, glyph, byte_len);
6867  }
6868  return len;
6869 }
6870 
6871 NK_API int
6872 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
6873 {
6874  int i = 0;
6875  nk_glyph glyph;
6876  int byte_len;
6877  NK_ASSERT(str);
6878  if (!str || !runes) return 0;
6879  while (runes[i] != '\0') {
6880  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6881  nk_str_append_text_char(str, glyph, byte_len);
6882  i++;
6883  }
6884  return i;
6885 }
6886 
6887 NK_API int
6888 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
6889 {
6890  int i;
6891  void *mem;
6892  char *src;
6893  char *dst;
6894 
6895  int copylen;
6896  NK_ASSERT(s);
6897  NK_ASSERT(str);
6898  NK_ASSERT(len >= 0);
6899  if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
6900  if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
6901  (s->buffer.type == NK_BUFFER_FIXED)) return 0;
6902 
6903  copylen = (int)s->buffer.allocated - pos;
6904  if (!copylen) {
6905  nk_str_append_text_char(s, str, len);
6906  return 1;
6907  }
6908  mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6909  if (!mem) return 0;
6910 
6911  /* memmove */
6912  NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
6913  NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
6914  dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
6915  src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
6916  for (i = 0; i < copylen; ++i) *dst-- = *src--;
6917  mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
6918  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6919  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6920  return 1;
6921 }
6922 
6923 NK_API int
6924 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
6925 {
6926  int glyph_len;
6927  nk_rune unicode;
6928  const char *begin;
6929  const char *buffer;
6930 
6931  NK_ASSERT(str);
6932  NK_ASSERT(cstr);
6933  NK_ASSERT(len);
6934  if (!str || !cstr || !len) return 0;
6935  begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
6936  if (!str->len)
6937  return nk_str_append_text_char(str, cstr, len);
6938  buffer = nk_str_get_const(str);
6939  if (!begin) return 0;
6940  return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
6941 }
6942 
6943 NK_API int
6944 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
6945 {
6946  return nk_str_insert_text_utf8(str, pos, text, len);
6947 }
6948 
6949 NK_API int
6950 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
6951 {
6952  return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
6953 }
6954 
6955 NK_API int
6956 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
6957 {
6958  int i = 0;
6959  int byte_len = 0;
6960  nk_rune unicode;
6961 
6962  NK_ASSERT(str);
6963  NK_ASSERT(text);
6964  if (!str || !text || !len) return 0;
6965  for (i = 0; i < len; ++i)
6966  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6967  nk_str_insert_at_rune(str, pos, text, byte_len);
6968  return len;
6969 }
6970 
6971 NK_API int
6972 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
6973 {
6974  int runes = 0;
6975  int byte_len = 0;
6976  int num_runes = 0;
6977  int glyph_len = 0;
6978  nk_rune unicode;
6979  if (!str || !text) return 0;
6980 
6981  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6982  while (unicode != '\0' && glyph_len) {
6983  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6984  byte_len += glyph_len;
6985  num_runes++;
6986  }
6987  nk_str_insert_at_rune(str, pos, text, byte_len);
6988  return runes;
6989 }
6990 
6991 NK_API int
6992 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
6993 {
6994  int i = 0;
6995  int byte_len = 0;
6996  nk_glyph glyph;
6997 
6998  NK_ASSERT(str);
6999  if (!str || !runes || !len) return 0;
7000  for (i = 0; i < len; ++i) {
7001  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
7002  if (!byte_len) break;
7003  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
7004  }
7005  return len;
7006 }
7007 
7008 NK_API int
7009 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
7010 {
7011  int i = 0;
7012  nk_glyph glyph;
7013  int byte_len;
7014  NK_ASSERT(str);
7015  if (!str || !runes) return 0;
7016  while (runes[i] != '\0') {
7017  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
7018  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
7019  i++;
7020  }
7021  return i;
7022 }
7023 
7024 NK_API void
7025 nk_str_remove_chars(struct nk_str *s, int len)
7026 {
7027  NK_ASSERT(s);
7028  NK_ASSERT(len >= 0);
7029  if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
7030  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
7031  s->buffer.allocated -= (nk_size)len;
7032  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
7033 }
7034 
7035 NK_API void
7036 nk_str_remove_runes(struct nk_str *str, int len)
7037 {
7038  int index;
7039  const char *begin;
7040  const char *end;
7041  nk_rune unicode;
7042 
7043  NK_ASSERT(str);
7044  NK_ASSERT(len >= 0);
7045  if (!str || len < 0) return;
7046  if (len >= str->len) {
7047  str->len = 0;
7048  return;
7049  }
7050 
7051  index = str->len - len;
7052  begin = nk_str_at_rune(str, index, &unicode, &len);
7053  end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
7054  nk_str_remove_chars(str, (int)(end-begin)+1);
7055 }
7056 
7057 NK_API void
7058 nk_str_delete_chars(struct nk_str *s, int pos, int len)
7059 {
7060  NK_ASSERT(s);
7061  if (!s || !len || (nk_size)pos > s->buffer.allocated ||
7062  (nk_size)(pos + len) > s->buffer.allocated) return;
7063 
7064  if ((nk_size)(pos + len) < s->buffer.allocated) {
7065  /* memmove */
7066  char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
7067  char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
7068  NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
7069  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
7070  s->buffer.allocated -= (nk_size)len;
7071  } else nk_str_remove_chars(s, len);
7072  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
7073 }
7074 
7075 NK_API void
7076 nk_str_delete_runes(struct nk_str *s, int pos, int len)
7077 {
7078  char *temp;
7079  nk_rune unicode;
7080  char *begin;
7081  char *end;
7082  int unused;
7083 
7084  NK_ASSERT(s);
7085  NK_ASSERT(s->len >= pos + len);
7086  if (s->len < pos + len)
7087  len = NK_CLAMP(0, (s->len - pos), s->len);
7088  if (!len) return;
7089 
7090  temp = (char *)s->buffer.memory.ptr;
7091  begin = nk_str_at_rune(s, pos, &unicode, &unused);
7092  if (!begin) return;
7093  s->buffer.memory.ptr = begin;
7094  end = nk_str_at_rune(s, len, &unicode, &unused);
7095  s->buffer.memory.ptr = temp;
7096  if (!end) return;
7097  nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
7098 }
7099 
7100 NK_API char*
7101 nk_str_at_char(struct nk_str *s, int pos)
7102 {
7103  NK_ASSERT(s);
7104  if (!s || pos > (int)s->buffer.allocated) return 0;
7105  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7106 }
7107 
7108 NK_API char*
7109 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
7110 {
7111  int i = 0;
7112  int src_len = 0;
7113  int glyph_len = 0;
7114  char *text;
7115  int text_len;
7116 
7117  NK_ASSERT(str);
7118  NK_ASSERT(unicode);
7119  NK_ASSERT(len);
7120 
7121  if (!str || !unicode || !len) return 0;
7122  if (pos < 0) {
7123  *unicode = 0;
7124  *len = 0;
7125  return 0;
7126  }
7127 
7128  text = (char*)str->buffer.memory.ptr;
7129  text_len = (int)str->buffer.allocated;
7130  glyph_len = nk_utf_decode(text, unicode, text_len);
7131  while (glyph_len) {
7132  if (i == pos) {
7133  *len = glyph_len;
7134  break;
7135  }
7136 
7137  i++;
7138  src_len = src_len + glyph_len;
7139  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7140  }
7141  if (i != pos) return 0;
7142  return text + src_len;
7143 }
7144 
7145 NK_API const char*
7146 nk_str_at_char_const(const struct nk_str *s, int pos)
7147 {
7148  NK_ASSERT(s);
7149  if (!s || pos > (int)s->buffer.allocated) return 0;
7150  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7151 }
7152 
7153 NK_API const char*
7154 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
7155 {
7156  int i = 0;
7157  int src_len = 0;
7158  int glyph_len = 0;
7159  char *text;
7160  int text_len;
7161 
7162  NK_ASSERT(str);
7163  NK_ASSERT(unicode);
7164  NK_ASSERT(len);
7165 
7166  if (!str || !unicode || !len) return 0;
7167  if (pos < 0) {
7168  *unicode = 0;
7169  *len = 0;
7170  return 0;
7171  }
7172 
7173  text = (char*)str->buffer.memory.ptr;
7174  text_len = (int)str->buffer.allocated;
7175  glyph_len = nk_utf_decode(text, unicode, text_len);
7176  while (glyph_len) {
7177  if (i == pos) {
7178  *len = glyph_len;
7179  break;
7180  }
7181 
7182  i++;
7183  src_len = src_len + glyph_len;
7184  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7185  }
7186  if (i != pos) return 0;
7187  return text + src_len;
7188 }
7189 
7190 NK_API nk_rune
7191 nk_str_rune_at(const struct nk_str *str, int pos)
7192 {
7193  int len;
7194  nk_rune unicode = 0;
7195  nk_str_at_const(str, pos, &unicode, &len);
7196  return unicode;
7197 }
7198 
7199 NK_API char*
7200 nk_str_get(struct nk_str *s)
7201 {
7202  NK_ASSERT(s);
7203  if (!s || !s->len || !s->buffer.allocated) return 0;
7204  return (char*)s->buffer.memory.ptr;
7205 }
7206 
7207 NK_API const char*
7208 nk_str_get_const(const struct nk_str *s)
7209 {
7210  NK_ASSERT(s);
7211  if (!s || !s->len || !s->buffer.allocated) return 0;
7212  return (const char*)s->buffer.memory.ptr;
7213 }
7214 
7215 NK_API int
7216 nk_str_len(struct nk_str *s)
7217 {
7218  NK_ASSERT(s);
7219  if (!s || !s->len || !s->buffer.allocated) return 0;
7220  return s->len;
7221 }
7222 
7223 NK_API int
7224 nk_str_len_char(struct nk_str *s)
7225 {
7226  NK_ASSERT(s);
7227  if (!s || !s->len || !s->buffer.allocated) return 0;
7228  return (int)s->buffer.allocated;
7229 }
7230 
7231 NK_API void
7232 nk_str_clear(struct nk_str *str)
7233 {
7234  NK_ASSERT(str);
7235  nk_buffer_clear(&str->buffer);
7236  str->len = 0;
7237 }
7238 
7239 NK_API void
7240 nk_str_free(struct nk_str *str)
7241 {
7242  NK_ASSERT(str);
7243  nk_buffer_free(&str->buffer);
7244  str->len = 0;
7245 }
7246 
7247 /*
7248  * ==============================================================
7249  *
7250  * Command buffer
7251  *
7252  * ===============================================================
7253 */
7254 NK_INTERN void
7255 nk_command_buffer_init(struct nk_command_buffer *cmdbuf,
7256  struct nk_buffer *buffer, enum nk_command_clipping clip)
7257 {
7258  NK_ASSERT(cmdbuf);
7259  NK_ASSERT(buffer);
7260  if (!cmdbuf || !buffer) return;
7261  cmdbuf->base = buffer;
7262  cmdbuf->use_clipping = clip;
7263  cmdbuf->begin = buffer->allocated;
7264  cmdbuf->end = buffer->allocated;
7265  cmdbuf->last = buffer->allocated;
7266 }
7267 
7268 NK_INTERN void
7269 nk_command_buffer_reset(struct nk_command_buffer *buffer)
7270 {
7271  NK_ASSERT(buffer);
7272  if (!buffer) return;
7273  buffer->begin = 0;
7274  buffer->end = 0;
7275  buffer->last = 0;
7276  buffer->clip = nk_null_rect;
7277 #ifdef NK_INCLUDE_COMMAND_USERDATA
7278  buffer->userdata.ptr = 0;
7279 #endif
7280 }
7281 
7282 NK_INTERN void*
7283 nk_command_buffer_push(struct nk_command_buffer* b,
7284  enum nk_command_type t, nk_size size)
7285 {
7286  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
7287  struct nk_command *cmd;
7288  nk_size alignment;
7289  void *unaligned;
7290  void *memory;
7291 
7292  NK_ASSERT(b);
7293  NK_ASSERT(b->base);
7294  if (!b) return 0;
7295  cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
7296  if (!cmd) return 0;
7297 
7298  /* make sure the offset to the next command is aligned */
7299  b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
7300  unaligned = (nk_byte*)cmd + size;
7301  memory = NK_ALIGN_PTR(unaligned, align);
7302  alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7303 #ifdef NK_ZERO_COMMAND_MEMORY
7304  NK_MEMSET(cmd, 0, size + alignment);
7305 #endif
7306 
7307  cmd->type = t;
7308  cmd->next = b->base->allocated + alignment;
7309 #ifdef NK_INCLUDE_COMMAND_USERDATA
7310  cmd->userdata = b->userdata;
7311 #endif
7312  b->end = cmd->next;
7313  return cmd;
7314 }
7315 
7316 NK_API void
7317 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
7318 {
7319  struct nk_command_scissor *cmd;
7320  NK_ASSERT(b);
7321  if (!b) return;
7322 
7323  b->clip.x = r.x;
7324  b->clip.y = r.y;
7325  b->clip.w = r.w;
7326  b->clip.h = r.h;
7327  cmd = (struct nk_command_scissor*)
7328  nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
7329 
7330  if (!cmd) return;
7331  cmd->x = (short)r.x;
7332  cmd->y = (short)r.y;
7333  cmd->w = (unsigned short)NK_MAX(0, r.w);
7334  cmd->h = (unsigned short)NK_MAX(0, r.h);
7335 }
7336 
7337 NK_API void
7338 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
7339  float x1, float y1, float line_thickness, struct nk_color c)
7340 {
7341  struct nk_command_line *cmd;
7342  NK_ASSERT(b);
7343  if (!b || line_thickness <= 0) return;
7344  cmd = (struct nk_command_line*)
7345  nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
7346  if (!cmd) return;
7347  cmd->line_thickness = (unsigned short)line_thickness;
7348  cmd->begin.x = (short)x0;
7349  cmd->begin.y = (short)y0;
7350  cmd->end.x = (short)x1;
7351  cmd->end.y = (short)y1;
7352  cmd->color = c;
7353 }
7354 
7355 NK_API void
7356 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
7357  float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
7358  float bx, float by, float line_thickness, struct nk_color col)
7359 {
7360  struct nk_command_curve *cmd;
7361  NK_ASSERT(b);
7362  if (!b || col.a == 0 || line_thickness <= 0) return;
7363 
7364  cmd = (struct nk_command_curve*)
7365  nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
7366  if (!cmd) return;
7367  cmd->line_thickness = (unsigned short)line_thickness;
7368  cmd->begin.x = (short)ax;
7369  cmd->begin.y = (short)ay;
7370  cmd->ctrl[0].x = (short)ctrl0x;
7371  cmd->ctrl[0].y = (short)ctrl0y;
7372  cmd->ctrl[1].x = (short)ctrl1x;
7373  cmd->ctrl[1].y = (short)ctrl1y;
7374  cmd->end.x = (short)bx;
7375  cmd->end.y = (short)by;
7376  cmd->color = col;
7377 }
7378 
7379 NK_API void
7380 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
7381  float rounding, float line_thickness, struct nk_color c)
7382 {
7383  struct nk_command_rect *cmd;
7384  NK_ASSERT(b);
7385  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
7386  if (b->use_clipping) {
7387  const struct nk_rect *clip = &b->clip;
7388  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7389  clip->x, clip->y, clip->w, clip->h)) return;
7390  }
7391  cmd = (struct nk_command_rect*)
7392  nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
7393  if (!cmd) return;
7394  cmd->rounding = (unsigned short)rounding;
7395  cmd->line_thickness = (unsigned short)line_thickness;
7396  cmd->x = (short)rect.x;
7397  cmd->y = (short)rect.y;
7398  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7399  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7400  cmd->color = c;
7401 }
7402 
7403 NK_API void
7404 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
7405  float rounding, struct nk_color c)
7406 {
7407  struct nk_command_rect_filled *cmd;
7408  NK_ASSERT(b);
7409  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7410  if (b->use_clipping) {
7411  const struct nk_rect *clip = &b->clip;
7412  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7413  clip->x, clip->y, clip->w, clip->h)) return;
7414  }
7415 
7416  cmd = (struct nk_command_rect_filled*)
7417  nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
7418  if (!cmd) return;
7419  cmd->rounding = (unsigned short)rounding;
7420  cmd->x = (short)rect.x;
7421  cmd->y = (short)rect.y;
7422  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7423  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7424  cmd->color = c;
7425 }
7426 
7427 NK_API void
7428 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect,
7429  struct nk_color left, struct nk_color top, struct nk_color right,
7430  struct nk_color bottom)
7431 {
7432  struct nk_command_rect_multi_color *cmd;
7433  NK_ASSERT(b);
7434  if (!b || rect.w == 0 || rect.h == 0) return;
7435  if (b->use_clipping) {
7436  const struct nk_rect *clip = &b->clip;
7437  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7438  clip->x, clip->y, clip->w, clip->h)) return;
7439  }
7440 
7441  cmd = (struct nk_command_rect_multi_color*)
7442  nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
7443  if (!cmd) return;
7444  cmd->x = (short)rect.x;
7445  cmd->y = (short)rect.y;
7446  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7447  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7448  cmd->left = left;
7449  cmd->top = top;
7450  cmd->right = right;
7451  cmd->bottom = bottom;
7452 }
7453 
7454 NK_API void
7455 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
7456  float line_thickness, struct nk_color c)
7457 {
7458  struct nk_command_circle *cmd;
7459  if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
7460  if (b->use_clipping) {
7461  const struct nk_rect *clip = &b->clip;
7462  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7463  return;
7464  }
7465 
7466  cmd = (struct nk_command_circle*)
7467  nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
7468  if (!cmd) return;
7469  cmd->line_thickness = (unsigned short)line_thickness;
7470  cmd->x = (short)r.x;
7471  cmd->y = (short)r.y;
7472  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7473  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7474  cmd->color = c;
7475 }
7476 
7477 NK_API void
7478 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
7479 {
7480  struct nk_command_circle_filled *cmd;
7481  NK_ASSERT(b);
7482  if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
7483  if (b->use_clipping) {
7484  const struct nk_rect *clip = &b->clip;
7485  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7486  return;
7487  }
7488 
7489  cmd = (struct nk_command_circle_filled*)
7490  nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
7491  if (!cmd) return;
7492  cmd->x = (short)r.x;
7493  cmd->y = (short)r.y;
7494  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7495  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7496  cmd->color = c;
7497 }
7498 
7499 NK_API void
7500 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7501  float a_min, float a_max, float line_thickness, struct nk_color c)
7502 {
7503  struct nk_command_arc *cmd;
7504  if (!b || c.a == 0 || line_thickness <= 0) return;
7505  cmd = (struct nk_command_arc*)
7506  nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
7507  if (!cmd) return;
7508  cmd->line_thickness = (unsigned short)line_thickness;
7509  cmd->cx = (short)cx;
7510  cmd->cy = (short)cy;
7511  cmd->r = (unsigned short)radius;
7512  cmd->a[0] = a_min;
7513  cmd->a[1] = a_max;
7514  cmd->color = c;
7515 }
7516 
7517 NK_API void
7518 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7519  float a_min, float a_max, struct nk_color c)
7520 {
7521  struct nk_command_arc_filled *cmd;
7522  NK_ASSERT(b);
7523  if (!b || c.a == 0) return;
7524  cmd = (struct nk_command_arc_filled*)
7525  nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
7526  if (!cmd) return;
7527  cmd->cx = (short)cx;
7528  cmd->cy = (short)cy;
7529  cmd->r = (unsigned short)radius;
7530  cmd->a[0] = a_min;
7531  cmd->a[1] = a_max;
7532  cmd->color = c;
7533 }
7534 
7535 NK_API void
7536 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7537  float y1, float x2, float y2, float line_thickness, struct nk_color c)
7538 {
7539  struct nk_command_triangle *cmd;
7540  NK_ASSERT(b);
7541  if (!b || c.a == 0 || line_thickness <= 0) return;
7542  if (b->use_clipping) {
7543  const struct nk_rect *clip = &b->clip;
7544  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7545  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7546  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7547  return;
7548  }
7549 
7550  cmd = (struct nk_command_triangle*)
7551  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
7552  if (!cmd) return;
7553  cmd->line_thickness = (unsigned short)line_thickness;
7554  cmd->a.x = (short)x0;
7555  cmd->a.y = (short)y0;
7556  cmd->b.x = (short)x1;
7557  cmd->b.y = (short)y1;
7558  cmd->c.x = (short)x2;
7559  cmd->c.y = (short)y2;
7560  cmd->color = c;
7561 }
7562 
7563 NK_API void
7564 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7565  float y1, float x2, float y2, struct nk_color c)
7566 {
7567  struct nk_command_triangle_filled *cmd;
7568  NK_ASSERT(b);
7569  if (!b || c.a == 0) return;
7570  if (!b) return;
7571  if (b->use_clipping) {
7572  const struct nk_rect *clip = &b->clip;
7573  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7574  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7575  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7576  return;
7577  }
7578 
7579  cmd = (struct nk_command_triangle_filled*)
7580  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
7581  if (!cmd) return;
7582  cmd->a.x = (short)x0;
7583  cmd->a.y = (short)y0;
7584  cmd->b.x = (short)x1;
7585  cmd->b.y = (short)y1;
7586  cmd->c.x = (short)x2;
7587  cmd->c.y = (short)y2;
7588  cmd->color = c;
7589 }
7590 
7591 NK_API void
7592 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count,
7593  float line_thickness, struct nk_color col)
7594 {
7595  int i;
7596  nk_size size = 0;
7597  struct nk_command_polygon *cmd;
7598 
7599  NK_ASSERT(b);
7600  if (!b || col.a == 0 || line_thickness <= 0) return;
7601  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7602  cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
7603  if (!cmd) return;
7604  cmd->color = col;
7605  cmd->line_thickness = (unsigned short)line_thickness;
7606  cmd->point_count = (unsigned short)point_count;
7607  for (i = 0; i < point_count; ++i) {
7608  cmd->points[i].x = (short)points[i*2];
7609  cmd->points[i].y = (short)points[i*2+1];
7610  }
7611 }
7612 
7613 NK_API void
7614 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count,
7615  struct nk_color col)
7616 {
7617  int i;
7618  nk_size size = 0;
7619  struct nk_command_polygon_filled *cmd;
7620 
7621  NK_ASSERT(b);
7622  if (!b || col.a == 0) return;
7623  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7624  cmd = (struct nk_command_polygon_filled*)
7625  nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
7626  if (!cmd) return;
7627  cmd->color = col;
7628  cmd->point_count = (unsigned short)point_count;
7629  for (i = 0; i < point_count; ++i) {
7630  cmd->points[i].x = (short)points[i*2+0];
7631  cmd->points[i].y = (short)points[i*2+1];
7632  }
7633 }
7634 
7635 NK_API void
7636 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count,
7637  float line_thickness, struct nk_color col)
7638 {
7639  int i;
7640  nk_size size = 0;
7641  struct nk_command_polyline *cmd;
7642 
7643  NK_ASSERT(b);
7644  if (!b || col.a == 0 || line_thickness <= 0) return;
7645  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7646  cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
7647  if (!cmd) return;
7648  cmd->color = col;
7649  cmd->point_count = (unsigned short)point_count;
7650  cmd->line_thickness = (unsigned short)line_thickness;
7651  for (i = 0; i < point_count; ++i) {
7652  cmd->points[i].x = (short)points[i*2];
7653  cmd->points[i].y = (short)points[i*2+1];
7654  }
7655 }
7656 
7657 NK_API void
7658 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
7659  const struct nk_image *img, struct nk_color col)
7660 {
7661  struct nk_command_image *cmd;
7662  NK_ASSERT(b);
7663  if (!b) return;
7664  if (b->use_clipping) {
7665  const struct nk_rect *c = &b->clip;
7666  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7667  return;
7668  }
7669 
7670  cmd = (struct nk_command_image*)
7671  nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
7672  if (!cmd) return;
7673  cmd->x = (short)r.x;
7674  cmd->y = (short)r.y;
7675  cmd->w = (unsigned short)NK_MAX(0, r.w);
7676  cmd->h = (unsigned short)NK_MAX(0, r.h);
7677  cmd->img = *img;
7678  cmd->col = col;
7679 }
7680 
7681 NK_API void
7682 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
7683  nk_command_custom_callback cb, nk_handle usr)
7684 {
7685  struct nk_command_custom *cmd;
7686  NK_ASSERT(b);
7687  if (!b) return;
7688  if (b->use_clipping) {
7689  const struct nk_rect *c = &b->clip;
7690  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7691  return;
7692  }
7693 
7694  cmd = (struct nk_command_custom*)
7695  nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
7696  if (!cmd) return;
7697  cmd->x = (short)r.x;
7698  cmd->y = (short)r.y;
7699  cmd->w = (unsigned short)NK_MAX(0, r.w);
7700  cmd->h = (unsigned short)NK_MAX(0, r.h);
7701  cmd->callback_data = usr;
7702  cmd->callback = cb;
7703 }
7704 
7705 NK_API void
7706 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
7707  const char *string, int length, const struct nk_user_font *font,
7708  struct nk_color bg, struct nk_color fg)
7709 {
7710  float text_width = 0;
7711  struct nk_command_text *cmd;
7712 
7713  NK_ASSERT(b);
7714  NK_ASSERT(font);
7715  if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
7716  if (b->use_clipping) {
7717  const struct nk_rect *c = &b->clip;
7718  if (c->w == 0 || c->h == 0 || !NK_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h))
7719  return;
7720  }
7721 
7722  /* make sure text fits inside bounds */
7723  text_width = font->width(font->userdata, font->height, string, length);
7724  if (text_width > r.w){
7725  int glyphs = 0;
7726  float txt_width = (float)text_width;
7727  length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
7728  }
7729 
7730  if (!length) return;
7731  cmd = (struct nk_command_text*)
7732  nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
7733  if (!cmd) return;
7734  cmd->x = (short)r.x;
7735  cmd->y = (short)r.y;
7736  cmd->w = (unsigned short)r.w;
7737  cmd->h = (unsigned short)r.h;
7738  cmd->background = bg;
7739  cmd->foreground = fg;
7740  cmd->font = font;
7741  cmd->length = length;
7742  cmd->height = font->height;
7743  NK_MEMCPY(cmd->string, string, (nk_size)length);
7744  cmd->string[length] = '\0';
7745 }
7746 
7747 /* ==============================================================
7748  *
7749  * DRAW LIST
7750  *
7751  * ===============================================================*/
7752 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
7753 NK_API void
7754 nk_draw_list_init(struct nk_draw_list *list)
7755 {
7756  nk_size i = 0;
7757  NK_ASSERT(list);
7758  if (!list) return;
7759  nk_zero(list, sizeof(*list));
7760  for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
7761  const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
7762  list->circle_vtx[i].x = (float)NK_COS(a);
7763  list->circle_vtx[i].y = (float)NK_SIN(a);
7764  }
7765 }
7766 
7767 NK_API void
7768 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
7769  struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
7770  enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
7771 {
7772  NK_ASSERT(canvas);
7773  NK_ASSERT(config);
7774  NK_ASSERT(cmds);
7775  NK_ASSERT(vertices);
7776  NK_ASSERT(elements);
7777  if (!canvas || !config || !cmds || !vertices || !elements)
7778  return;
7779 
7780  canvas->buffer = cmds;
7781  canvas->config = *config;
7782  canvas->elements = elements;
7783  canvas->vertices = vertices;
7784  canvas->line_AA = line_aa;
7785  canvas->shape_AA = shape_aa;
7786  canvas->clip_rect = nk_null_rect;
7787 }
7788 
7789 NK_API const struct nk_draw_command*
7790 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7791 {
7792  nk_byte *memory;
7793  nk_size offset;
7794  const struct nk_draw_command *cmd;
7795 
7796  NK_ASSERT(buffer);
7797  if (!buffer || !buffer->size || !canvas->cmd_count)
7798  return 0;
7799 
7800  memory = (nk_byte*)buffer->memory.ptr;
7801  offset = buffer->memory.size - canvas->cmd_offset;
7802  cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
7803  return cmd;
7804 }
7805 
7806 NK_API const struct nk_draw_command*
7807 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7808 {
7809  nk_size size;
7810  nk_size offset;
7811  nk_byte *memory;
7812  const struct nk_draw_command *end;
7813 
7814  NK_ASSERT(buffer);
7815  NK_ASSERT(canvas);
7816  if (!buffer || !canvas)
7817  return 0;
7818 
7819  memory = (nk_byte*)buffer->memory.ptr;
7820  size = buffer->memory.size;
7821  offset = size - canvas->cmd_offset;
7822  end = nk_ptr_add(const struct nk_draw_command, memory, offset);
7823  end -= (canvas->cmd_count-1);
7824  return end;
7825 }
7826 
7827 NK_API const struct nk_draw_command*
7828 nk__draw_list_next(const struct nk_draw_command *cmd,
7829  const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
7830 {
7831  const struct nk_draw_command *end;
7832  NK_ASSERT(buffer);
7833  NK_ASSERT(canvas);
7834  if (!cmd || !buffer || !canvas)
7835  return 0;
7836 
7837  end = nk__draw_list_end(canvas, buffer);
7838  if (cmd <= end) return 0;
7839  return (cmd-1);
7840 }
7841 
7842 NK_API void
7843 nk_draw_list_clear(struct nk_draw_list *list)
7844 {
7845  NK_ASSERT(list);
7846  if (!list) return;
7847  if (list->buffer)
7848  nk_buffer_clear(list->buffer);
7849  if (list->vertices)
7850  nk_buffer_clear(list->vertices);
7851  if (list->elements)
7852  nk_buffer_clear(list->elements);
7853 
7854  list->element_count = 0;
7855  list->vertex_count = 0;
7856  list->cmd_offset = 0;
7857  list->cmd_count = 0;
7858  list->path_count = 0;
7859  list->vertices = 0;
7860  list->elements = 0;
7861  list->clip_rect = nk_null_rect;
7862 }
7863 
7864 NK_INTERN struct nk_vec2*
7865 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
7866 {
7867  struct nk_vec2 *points;
7868  NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
7869  NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
7870  points = (struct nk_vec2*)
7871  nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
7872  point_size * (nk_size)count, point_align);
7873 
7874  if (!points) return 0;
7875  if (!list->path_offset) {
7876  void *memory = nk_buffer_memory(list->buffer);
7877  list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
7878  }
7879  list->path_count += (unsigned int)count;
7880  return points;
7881 }
7882 
7883 NK_INTERN struct nk_vec2
7884 nk_draw_list_path_last(struct nk_draw_list *list)
7885 {
7886  void *memory;
7887  struct nk_vec2 *point;
7888  NK_ASSERT(list->path_count);
7889  memory = nk_buffer_memory(list->buffer);
7890  point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
7891  point += (list->path_count-1);
7892  return *point;
7893 }
7894 
7895 NK_INTERN struct nk_draw_command*
7896 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
7897  nk_handle texture)
7898 {
7899  NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
7900  NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
7901  struct nk_draw_command *cmd;
7902 
7903  NK_ASSERT(list);
7904  cmd = (struct nk_draw_command*)
7905  nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
7906 
7907  if (!cmd) return 0;
7908  if (!list->cmd_count) {
7909  nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
7910  nk_size total = nk_buffer_total(list->buffer);
7911  memory = nk_ptr_add(nk_byte, memory, total);
7912  list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
7913  }
7914 
7915  cmd->elem_count = 0;
7916  cmd->clip_rect = clip;
7917  cmd->texture = texture;
7918 #ifdef NK_INCLUDE_COMMAND_USERDATA
7919  cmd->userdata = list->userdata;
7920 #endif
7921 
7922  list->cmd_count++;
7923  list->clip_rect = clip;
7924  return cmd;
7925 }
7926 
7927 NK_INTERN struct nk_draw_command*
7928 nk_draw_list_command_last(struct nk_draw_list *list)
7929 {
7930  void *memory;
7931  nk_size size;
7932  struct nk_draw_command *cmd;
7933  NK_ASSERT(list->cmd_count);
7934 
7935  memory = nk_buffer_memory(list->buffer);
7936  size = nk_buffer_total(list->buffer);
7937  cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
7938  return (cmd - (list->cmd_count-1));
7939 }
7940 
7941 NK_INTERN void
7942 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
7943 {
7944  NK_ASSERT(list);
7945  if (!list) return;
7946  if (!list->cmd_count) {
7947  nk_draw_list_push_command(list, rect, list->config.null.texture);
7948  } else {
7949  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7950  if (prev->elem_count == 0)
7951  prev->clip_rect = rect;
7952  nk_draw_list_push_command(list, rect, prev->texture);
7953  }
7954 }
7955 
7956 NK_INTERN void
7957 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
7958 {
7959  NK_ASSERT(list);
7960  if (!list) return;
7961  if (!list->cmd_count) {
7962  nk_draw_list_push_command(list, nk_null_rect, texture);
7963  } else {
7964  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7965  if (prev->elem_count == 0)
7966  {
7967  prev->texture = texture;
7968 #ifdef NK_INCLUDE_COMMAND_USERDATA
7969  prev->userdata = list->userdata;
7970 #endif // NK_INCLUDE_COMMAND_USERDATA
7971  }
7972  else if (prev->texture.id != texture.id
7974  || prev->userdata.id != list->userdata.id
7975 #endif // NK_INCLUDE_COMMAND_USERDATA
7976  )
7977  nk_draw_list_push_command(list, prev->clip_rect, texture);
7978  }
7979 }
7980 
7981 #ifdef NK_INCLUDE_COMMAND_USERDATA
7982 NK_API void
7983 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
7984 {
7985  list->userdata = userdata;
7986 }
7987 #endif
7988 
7989 NK_INTERN void*
7990 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
7991 {
7992  void *vtx;
7993  NK_ASSERT(list);
7994  if (!list) return 0;
7995  vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
7996  list->config.vertex_size*count, list->config.vertex_alignment);
7997  if (!vtx) return 0;
7998  list->vertex_count += (unsigned int)count;
7999  return vtx;
8000 }
8001 
8002 NK_INTERN nk_draw_index*
8003 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
8004 {
8005  nk_draw_index *ids;
8006  struct nk_draw_command *cmd;
8007  NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
8008  NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
8009  NK_ASSERT(list);
8010  if (!list) return 0;
8011 
8012  ids = (nk_draw_index*)
8013  nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
8014  if (!ids) return 0;
8015  cmd = nk_draw_list_command_last(list);
8016  list->element_count += (unsigned int)count;
8017  cmd->elem_count += (unsigned int)count;
8018  return ids;
8019 }
8020 
8021 NK_INTERN int
8022 nk_draw_vertex_layout_element_is_end_of_layout(
8023  const struct nk_draw_vertex_layout_element *element)
8024 {
8025  return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
8026  element->format == NK_FORMAT_COUNT);
8027 }
8028 
8029 NK_INTERN void
8030 nk_draw_vertex_color(void *attribute, const float *values,
8031  enum nk_draw_vertex_layout_format format)
8032 {
8033  /* if this triggers you tried to provide a value format for a color */
8034  NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
8035  NK_ASSERT(format <= NK_FORMAT_COLOR_END);
8036  if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
8037 
8038  switch (format) {
8039  default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
8040  case NK_FORMAT_R8G8B8A8:
8041  case NK_FORMAT_R8G8B8: {
8042  struct nk_color col = nk_rgba_fv(values);
8043  NK_MEMCPY(attribute, &col.r, sizeof(col));
8044  } break;
8045  case NK_FORMAT_B8G8R8A8: {
8046  struct nk_color col = nk_rgba_fv(values);
8047  struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
8048  NK_MEMCPY(attribute, &bgra, sizeof(bgra));
8049  } break;
8050  case NK_FORMAT_R16G15B16: {
8051  nk_ushort col[3];
8052  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
8053  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
8054  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
8055  NK_MEMCPY(attribute, col, sizeof(col));
8056  } break;
8057  case NK_FORMAT_R16G15B16A16: {
8058  nk_ushort col[4];
8059  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
8060  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
8061  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
8062  col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX);
8063  NK_MEMCPY(attribute, col, sizeof(col));
8064  } break;
8065  case NK_FORMAT_R32G32B32: {
8066  nk_uint col[3];
8067  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
8068  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
8069  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
8070  NK_MEMCPY(attribute, col, sizeof(col));
8071  } break;
8072  case NK_FORMAT_R32G32B32A32: {
8073  nk_uint col[4];
8074  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
8075  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
8076  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
8077  col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX);
8078  NK_MEMCPY(attribute, col, sizeof(col));
8079  } break;
8080  case NK_FORMAT_R32G32B32A32_FLOAT:
8081  NK_MEMCPY(attribute, values, sizeof(float)*4);
8082  break;
8083  case NK_FORMAT_R32G32B32A32_DOUBLE: {
8084  double col[4];
8085  col[0] = (double)NK_SATURATE(values[0]);
8086  col[1] = (double)NK_SATURATE(values[1]);
8087  col[2] = (double)NK_SATURATE(values[2]);
8088  col[3] = (double)NK_SATURATE(values[3]);
8089  NK_MEMCPY(attribute, col, sizeof(col));
8090  } break;
8091  case NK_FORMAT_RGB32:
8092  case NK_FORMAT_RGBA32: {
8093  struct nk_color col = nk_rgba_fv(values);
8094  nk_uint color = nk_color_u32(col);
8095  NK_MEMCPY(attribute, &color, sizeof(color));
8096  } break;
8097  }
8098 }
8099 
8100 NK_INTERN void
8101 nk_draw_vertex_element(void *dst, const float *values, int value_count,
8102  enum nk_draw_vertex_layout_format format)
8103 {
8104  int value_index;
8105  void *attribute = dst;
8106  /* if this triggers you tried to provide a color format for a value */
8107  NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
8108  if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
8109  for (value_index = 0; value_index < value_count; ++value_index) {
8110  switch (format) {
8111  default: NK_ASSERT(0 && "invalid vertex layout format"); break;
8112  case NK_FORMAT_SCHAR: {
8113  char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX);
8114  NK_MEMCPY(attribute, &value, sizeof(value));
8115  attribute = (void*)((char*)attribute + sizeof(char));
8116  } break;
8117  case NK_FORMAT_SSHORT: {
8118  nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX);
8119  NK_MEMCPY(attribute, &value, sizeof(value));
8120  attribute = (void*)((char*)attribute + sizeof(value));
8121  } break;
8122  case NK_FORMAT_SINT: {
8123  nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX);
8124  NK_MEMCPY(attribute, &value, sizeof(value));
8125  attribute = (void*)((char*)attribute + sizeof(nk_int));
8126  } break;
8127  case NK_FORMAT_UCHAR: {
8128  unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX);
8129  NK_MEMCPY(attribute, &value, sizeof(value));
8130  attribute = (void*)((char*)attribute + sizeof(unsigned char));
8131  } break;
8132  case NK_FORMAT_USHORT: {
8133  nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX);
8134  NK_MEMCPY(attribute, &value, sizeof(value));
8135  attribute = (void*)((char*)attribute + sizeof(value));
8136  } break;
8137  case NK_FORMAT_UINT: {
8138  nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX);
8139  NK_MEMCPY(attribute, &value, sizeof(value));
8140  attribute = (void*)((char*)attribute + sizeof(nk_uint));
8141  } break;
8142  case NK_FORMAT_FLOAT:
8143  NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
8144  attribute = (void*)((char*)attribute + sizeof(float));
8145  break;
8146  case NK_FORMAT_DOUBLE: {
8147  double value = (double)values[value_index];
8148  NK_MEMCPY(attribute, &value, sizeof(value));
8149  attribute = (void*)((char*)attribute + sizeof(double));
8150  } break;
8151  }
8152  }
8153 }
8154 
8155 NK_INTERN void*
8156 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
8157  struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
8158 {
8159  void *result = (void*)((char*)dst + config->vertex_size);
8160  const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
8161  while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
8162  void *address = (void*)((char*)dst + elem_iter->offset);
8163  switch (elem_iter->attribute) {
8164  case NK_VERTEX_ATTRIBUTE_COUNT:
8165  default: NK_ASSERT(0 && "wrong element attribute");
8166  case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
8167  case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
8168  case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
8169  }
8170  elem_iter++;
8171  }
8172  return result;
8173 }
8174 
8175 NK_API void
8176 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
8177  const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
8178  float thickness, enum nk_anti_aliasing aliasing)
8179 {
8180  nk_size count;
8181  int thick_line;
8182  struct nk_colorf col;
8183  struct nk_colorf col_trans;
8184  NK_ASSERT(list);
8185  if (!list || points_count < 2) return;
8186 
8187  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8188  count = points_count;
8189  if (!closed) count = points_count-1;
8190  thick_line = thickness > 1.0f;
8191 
8192 #ifdef NK_INCLUDE_COMMAND_USERDATA
8193  nk_draw_list_push_userdata(list, list->userdata);
8194 #endif
8195 
8196  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8197  nk_color_fv(&col.r, color);
8198  col_trans = col;
8199  col_trans.a = 0;
8200 
8201  if (aliasing == NK_ANTI_ALIASING_ON) {
8202  /* ANTI-ALIASED STROKE */
8203  const float AA_SIZE = 1.0f;
8204  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8205  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8206 
8207  /* allocate vertices and elements */
8208  nk_size i1 = 0;
8209  nk_size vertex_offset;
8210  nk_size index = list->vertex_count;
8211 
8212  const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
8213  const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
8214 
8215  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8216  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8217 
8218  nk_size size;
8219  struct nk_vec2 *normals, *temp;
8220  if (!vtx || !ids) return;
8221 
8222  /* temporary allocate normals + points */
8223  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8224  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8225  size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
8226  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8227  NK_ASSERT(normals);
8228  if (!normals) return;
8229  temp = normals + points_count;
8230 
8231  /* make sure vertex pointer is still correct */
8232  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8233 
8234  /* calculate normals */
8235  for (i1 = 0; i1 < count; ++i1) {
8236  const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8237  struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
8238  float len;
8239 
8240  /* vec2 inverted length */
8241  len = nk_vec2_len_sqr(diff);
8242  if (len != 0.0f)
8243  len = nk_inv_sqrt(len);
8244  else len = 1.0f;
8245 
8246  diff = nk_vec2_muls(diff, len);
8247  normals[i1].x = diff.y;
8248  normals[i1].y = -diff.x;
8249  }
8250 
8251  if (!closed)
8252  normals[points_count-1] = normals[points_count-2];
8253 
8254  if (!thick_line) {
8255  nk_size idx1, i;
8256  if (!closed) {
8257  struct nk_vec2 d;
8258  temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8259  temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8260  d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
8261  temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
8262  temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
8263  }
8264 
8265  /* fill elements */
8266  idx1 = index;
8267  for (i1 = 0; i1 < count; i1++) {
8268  struct nk_vec2 dm;
8269  float dmr2;
8270  nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8271  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
8272 
8273  /* average normals */
8274  dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8275  dmr2 = dm.x * dm.x + dm.y* dm.y;
8276  if (dmr2 > 0.000001f) {
8277  float scale = 1.0f/dmr2;
8278  scale = NK_MIN(100.0f, scale);
8279  dm = nk_vec2_muls(dm, scale);
8280  }
8281 
8282  dm = nk_vec2_muls(dm, AA_SIZE);
8283  temp[i2*2+0] = nk_vec2_add(points[i2], dm);
8284  temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
8285 
8286  ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
8287  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8288  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
8289  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8290  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8291  ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
8292  ids += 12;
8293  idx1 = idx2;
8294  }
8295 
8296  /* fill vertices */
8297  for (i = 0; i < points_count; ++i) {
8298  const struct nk_vec2 uv = list->config.null.uv;
8299  vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
8300  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
8301  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
8302  }
8303  } else {
8304  nk_size idx1, i;
8305  const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
8306  if (!closed) {
8307  struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
8308  struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
8309 
8310  temp[0] = nk_vec2_add(points[0], d1);
8311  temp[1] = nk_vec2_add(points[0], d2);
8312  temp[2] = nk_vec2_sub(points[0], d2);
8313  temp[3] = nk_vec2_sub(points[0], d1);
8314 
8315  d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
8316  d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
8317 
8318  temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
8319  temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
8320  temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
8321  temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
8322  }
8323 
8324  /* add all elements */
8325  idx1 = index;
8326  for (i1 = 0; i1 < count; ++i1) {
8327  struct nk_vec2 dm_out, dm_in;
8328  const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
8329  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
8330 
8331  /* average normals */
8332  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8333  float dmr2 = dm.x * dm.x + dm.y* dm.y;
8334  if (dmr2 > 0.000001f) {
8335  float scale = 1.0f/dmr2;
8336  scale = NK_MIN(100.0f, scale);
8337  dm = nk_vec2_muls(dm, scale);
8338  }
8339 
8340  dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
8341  dm_in = nk_vec2_muls(dm, half_inner_thickness);
8342  temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
8343  temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
8344  temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
8345  temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
8346 
8347  /* add indexes */
8348  ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
8349  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8350  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
8351  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8352  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8353  ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
8354  ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
8355  ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
8356  ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
8357  ids += 18;
8358  idx1 = idx2;
8359  }
8360 
8361  /* add vertices */
8362  for (i = 0; i < points_count; ++i) {
8363  const struct nk_vec2 uv = list->config.null.uv;
8364  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
8365  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
8366  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
8367  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
8368  }
8369  }
8370  /* free temporary normals + points */
8371  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8372  } else {
8373  /* NON ANTI-ALIASED STROKE */
8374  nk_size i1 = 0;
8375  nk_size idx = list->vertex_count;
8376  const nk_size idx_count = count * 6;
8377  const nk_size vtx_count = count * 4;
8378  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8379  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8380  if (!vtx || !ids) return;
8381 
8382  for (i1 = 0; i1 < count; ++i1) {
8383  float dx, dy;
8384  const struct nk_vec2 uv = list->config.null.uv;
8385  const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
8386  const struct nk_vec2 p1 = points[i1];
8387  const struct nk_vec2 p2 = points[i2];
8388  struct nk_vec2 diff = nk_vec2_sub(p2, p1);
8389  float len;
8390 
8391  /* vec2 inverted length */
8392  len = nk_vec2_len_sqr(diff);
8393  if (len != 0.0f)
8394  len = nk_inv_sqrt(len);
8395  else len = 1.0f;
8396  diff = nk_vec2_muls(diff, len);
8397 
8398  /* add vertices */
8399  dx = diff.x * (thickness * 0.5f);
8400  dy = diff.y * (thickness * 0.5f);
8401 
8402  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
8403  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
8404  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
8405  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
8406 
8407  ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
8408  ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
8409  ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
8410 
8411  ids += 6;
8412  idx += 4;
8413  }
8414  }
8415 }
8416 
8417 NK_API void
8418 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
8419  const struct nk_vec2 *points, const unsigned int points_count,
8420  struct nk_color color, enum nk_anti_aliasing aliasing)
8421 {
8422  struct nk_colorf col;
8423  struct nk_colorf col_trans;
8424 
8425  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8426  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8427  NK_ASSERT(list);
8428  if (!list || points_count < 3) return;
8429 
8430 #ifdef NK_INCLUDE_COMMAND_USERDATA
8431  nk_draw_list_push_userdata(list, list->userdata);
8432 #endif
8433 
8434  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8435  nk_color_fv(&col.r, color);
8436  col_trans = col;
8437  col_trans.a = 0;
8438 
8439  if (aliasing == NK_ANTI_ALIASING_ON) {
8440  nk_size i = 0;
8441  nk_size i0 = 0;
8442  nk_size i1 = 0;
8443 
8444  const float AA_SIZE = 1.0f;
8445  nk_size vertex_offset = 0;
8446  nk_size index = list->vertex_count;
8447 
8448  const nk_size idx_count = (points_count-2)*3 + points_count*6;
8449  const nk_size vtx_count = (points_count*2);
8450 
8451  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8452  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8453 
8454  nk_size size = 0;
8455  struct nk_vec2 *normals = 0;
8456  unsigned int vtx_inner_idx = (unsigned int)(index + 0);
8457  unsigned int vtx_outer_idx = (unsigned int)(index + 1);
8458  if (!vtx || !ids) return;
8459 
8460  /* temporary allocate normals */
8461  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8462  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8463  size = pnt_size * points_count;
8464  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8465  NK_ASSERT(normals);
8466  if (!normals) return;
8467  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8468 
8469  /* add elements */
8470  for (i = 2; i < points_count; i++) {
8471  ids[0] = (nk_draw_index)(vtx_inner_idx);
8472  ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
8473  ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
8474  ids += 3;
8475  }
8476 
8477  /* compute normals */
8478  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8479  struct nk_vec2 p0 = points[i0];
8480  struct nk_vec2 p1 = points[i1];
8481  struct nk_vec2 diff = nk_vec2_sub(p1, p0);
8482 
8483  /* vec2 inverted length */
8484  float len = nk_vec2_len_sqr(diff);
8485  if (len != 0.0f)
8486  len = nk_inv_sqrt(len);
8487  else len = 1.0f;
8488  diff = nk_vec2_muls(diff, len);
8489 
8490  normals[i0].x = diff.y;
8491  normals[i0].y = -diff.x;
8492  }
8493 
8494  /* add vertices + indexes */
8495  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8496  const struct nk_vec2 uv = list->config.null.uv;
8497  struct nk_vec2 n0 = normals[i0];
8498  struct nk_vec2 n1 = normals[i1];
8499  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
8500  float dmr2 = dm.x*dm.x + dm.y*dm.y;
8501  if (dmr2 > 0.000001f) {
8502  float scale = 1.0f / dmr2;
8503  scale = NK_MIN(scale, 100.0f);
8504  dm = nk_vec2_muls(dm, scale);
8505  }
8506  dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
8507 
8508  /* add vertices */
8509  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
8510  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
8511 
8512  /* add indexes */
8513  ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8514  ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
8515  ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8516  ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8517  ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
8518  ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8519  ids += 6;
8520  }
8521  /* free temporary normals + points */
8522  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8523  } else {
8524  nk_size i = 0;
8525  nk_size index = list->vertex_count;
8526  const nk_size idx_count = (points_count-2)*3;
8527  const nk_size vtx_count = points_count;
8528  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8529  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8530 
8531  if (!vtx || !ids) return;
8532  for (i = 0; i < vtx_count; ++i)
8533  vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
8534  for (i = 2; i < points_count; ++i) {
8535  ids[0] = (nk_draw_index)index;
8536  ids[1] = (nk_draw_index)(index+ i - 1);
8537  ids[2] = (nk_draw_index)(index+i);
8538  ids += 3;
8539  }
8540  }
8541 }
8542 
8543 NK_API void
8544 nk_draw_list_path_clear(struct nk_draw_list *list)
8545 {
8546  NK_ASSERT(list);
8547  if (!list) return;
8548  nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
8549  list->path_count = 0;
8550  list->path_offset = 0;
8551 }
8552 
8553 NK_API void
8554 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
8555 {
8556  struct nk_vec2 *points = 0;
8557  struct nk_draw_command *cmd = 0;
8558  NK_ASSERT(list);
8559  if (!list) return;
8560  if (!list->cmd_count)
8561  nk_draw_list_add_clip(list, nk_null_rect);
8562 
8563  cmd = nk_draw_list_command_last(list);
8564  if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
8565  nk_draw_list_push_image(list, list->config.null.texture);
8566 
8567  points = nk_draw_list_alloc_path(list, 1);
8568  if (!points) return;
8569  points[0] = pos;
8570 }
8571 
8572 NK_API void
8573 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
8574  float radius, int a_min, int a_max)
8575 {
8576  int a = 0;
8577  NK_ASSERT(list);
8578  if (!list) return;
8579  if (a_min <= a_max) {
8580  for (a = a_min; a <= a_max; a++) {
8581  const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
8582  const float x = center.x + c.x * radius;
8583  const float y = center.y + c.y * radius;
8584  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8585  }
8586  }
8587 }
8588 
8589 NK_API void
8590 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
8591  float radius, float a_min, float a_max, unsigned int segments)
8592 {
8593  unsigned int i = 0;
8594  NK_ASSERT(list);
8595  if (!list) return;
8596  if (radius == 0.0f) return;
8597 
8598  /* This algorithm for arc drawing relies on these two trigonometric identities[1]:
8599  sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
8600  cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
8601 
8602  Two coordinates (x, y) of a point on a circle centered on
8603  the origin can be written in polar form as:
8604  x = r * cos(a)
8605  y = r * sin(a)
8606  where r is the radius of the circle,
8607  a is the angle between (x, y) and the origin.
8608 
8609  This allows us to rotate the coordinates around the
8610  origin by an angle b using the following transformation:
8611  x' = r * cos(a + b) = x * cos(b) - y * sin(b)
8612  y' = r * sin(a + b) = y * cos(b) + x * sin(b)
8613 
8614  [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
8615  */
8616  const float d_angle = (a_max - a_min) / (float)segments;
8617  const float sin_d = (float)NK_SIN(d_angle);
8618  const float cos_d = (float)NK_COS(d_angle);
8619 
8620  float cx = (float)NK_COS(a_min) * radius;
8621  float cy = (float)NK_SIN(a_min) * radius;
8622  for(i = 0; i <= segments; ++i) {
8623  const float x = center.x + cx;
8624  const float y = center.y + cy;
8625  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8626 
8627  const float new_cx = cx * cos_d - cy * sin_d;
8628  const float new_cy = cy * cos_d + cx * sin_d;
8629  cx = new_cx;
8630  cy = new_cy;
8631  }
8632 }
8633 
8634 NK_API void
8635 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
8636  struct nk_vec2 b, float rounding)
8637 {
8638  float r;
8639  NK_ASSERT(list);
8640  if (!list) return;
8641  r = rounding;
8642  r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
8643  r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
8644 
8645  if (r == 0.0f) {
8646  nk_draw_list_path_line_to(list, a);
8647  nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
8648  nk_draw_list_path_line_to(list, b);
8649  nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
8650  } else {
8651  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
8652  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
8653  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
8654  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
8655  }
8656 }
8657 
8658 NK_API void
8659 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
8660  struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
8661 {
8662  float t_step;
8663  unsigned int i_step;
8664  struct nk_vec2 p1;
8665 
8666  NK_ASSERT(list);
8667  NK_ASSERT(list->path_count);
8668  if (!list || !list->path_count) return;
8669  num_segments = NK_MAX(num_segments, 1);
8670 
8671  p1 = nk_draw_list_path_last(list);
8672  t_step = 1.0f/(float)num_segments;
8673  for (i_step = 1; i_step <= num_segments; ++i_step) {
8674  float t = t_step * (float)i_step;
8675  float u = 1.0f - t;
8676  float w1 = u*u*u;
8677  float w2 = 3*u*u*t;
8678  float w3 = 3*u*t*t;
8679  float w4 = t * t *t;
8680  float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
8681  float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
8682  nk_draw_list_path_line_to(list, nk_vec2(x,y));
8683  }
8684 }
8685 
8686 NK_API void
8687 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
8688 {
8689  struct nk_vec2 *points;
8690  NK_ASSERT(list);
8691  if (!list) return;
8692  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8693  nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
8694  nk_draw_list_path_clear(list);
8695 }
8696 
8697 NK_API void
8698 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
8699  enum nk_draw_list_stroke closed, float thickness)
8700 {
8701  struct nk_vec2 *points;
8702  NK_ASSERT(list);
8703  if (!list) return;
8704  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8705  nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
8706  closed, thickness, list->config.line_AA);
8707  nk_draw_list_path_clear(list);
8708 }
8709 
8710 NK_API void
8711 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
8712  struct nk_vec2 b, struct nk_color col, float thickness)
8713 {
8714  NK_ASSERT(list);
8715  if (!list || !col.a) return;
8716  if (list->line_AA == NK_ANTI_ALIASING_ON) {
8717  nk_draw_list_path_line_to(list, a);
8718  nk_draw_list_path_line_to(list, b);
8719  } else {
8720  nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
8721  nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
8722  }
8723  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8724 }
8725 
8726 NK_API void
8727 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
8728  struct nk_color col, float rounding)
8729 {
8730  NK_ASSERT(list);
8731  if (!list || !col.a) return;
8732 
8733  if (list->line_AA == NK_ANTI_ALIASING_ON) {
8734  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
8735  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8736  } else {
8737  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
8738  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8739  } nk_draw_list_path_fill(list, col);
8740 }
8741 
8742 NK_API void
8743 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
8744  struct nk_color col, float rounding, float thickness)
8745 {
8746  NK_ASSERT(list);
8747  if (!list || !col.a) return;
8748  if (list->line_AA == NK_ANTI_ALIASING_ON) {
8749  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
8750  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8751  } else {
8752  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
8753  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8754  } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8755 }
8756 
8757 NK_API void
8758 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
8759  struct nk_color left, struct nk_color top, struct nk_color right,
8760  struct nk_color bottom)
8761 {
8762  void *vtx;
8763  struct nk_colorf col_left, col_top;
8764  struct nk_colorf col_right, col_bottom;
8765  nk_draw_index *idx;
8766  nk_draw_index index;
8767 
8768  nk_color_fv(&col_left.r, left);
8769  nk_color_fv(&col_right.r, right);
8770  nk_color_fv(&col_top.r, top);
8771  nk_color_fv(&col_bottom.r, bottom);
8772 
8773  NK_ASSERT(list);
8774  if (!list) return;
8775 
8776  nk_draw_list_push_image(list, list->config.null.texture);
8777  index = (nk_draw_index)list->vertex_count;
8778  vtx = nk_draw_list_alloc_vertices(list, 4);
8779  idx = nk_draw_list_alloc_elements(list, 6);
8780  if (!vtx || !idx) return;
8781 
8782  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8783  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8784  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8785 
8786  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
8787  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
8788  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
8789  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
8790 }
8791 
8792 NK_API void
8793 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8794  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
8795 {
8796  NK_ASSERT(list);
8797  if (!list || !col.a) return;
8798  nk_draw_list_path_line_to(list, a);
8799  nk_draw_list_path_line_to(list, b);
8800  nk_draw_list_path_line_to(list, c);
8801  nk_draw_list_path_fill(list, col);
8802 }
8803 
8804 NK_API void
8805 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8806  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
8807 {
8808  NK_ASSERT(list);
8809  if (!list || !col.a) return;
8810  nk_draw_list_path_line_to(list, a);
8811  nk_draw_list_path_line_to(list, b);
8812  nk_draw_list_path_line_to(list, c);
8813  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8814 }
8815 
8816 NK_API void
8817 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
8818  float radius, struct nk_color col, unsigned int segs)
8819 {
8820  float a_max;
8821  NK_ASSERT(list);
8822  if (!list || !col.a) return;
8823  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8824  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8825  nk_draw_list_path_fill(list, col);
8826 }
8827 
8828 NK_API void
8829 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
8830  float radius, struct nk_color col, unsigned int segs, float thickness)
8831 {
8832  float a_max;
8833  NK_ASSERT(list);
8834  if (!list || !col.a) return;
8835  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8836  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8837  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8838 }
8839 
8840 NK_API void
8841 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
8842  struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
8843  struct nk_color col, unsigned int segments, float thickness)
8844 {
8845  NK_ASSERT(list);
8846  if (!list || !col.a) return;
8847  nk_draw_list_path_line_to(list, p0);
8848  nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
8849  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8850 }
8851 
8852 NK_INTERN void
8853 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
8854  struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
8855  struct nk_color color)
8856 {
8857  void *vtx;
8858  struct nk_vec2 uvb;
8859  struct nk_vec2 uvd;
8860  struct nk_vec2 b;
8861  struct nk_vec2 d;
8862 
8863  struct nk_colorf col;
8864  nk_draw_index *idx;
8865  nk_draw_index index;
8866  NK_ASSERT(list);
8867  if (!list) return;
8868 
8869  nk_color_fv(&col.r, color);
8870  uvb = nk_vec2(uvc.x, uva.y);
8871  uvd = nk_vec2(uva.x, uvc.y);
8872  b = nk_vec2(c.x, a.y);
8873  d = nk_vec2(a.x, c.y);
8874 
8875  index = (nk_draw_index)list->vertex_count;
8876  vtx = nk_draw_list_alloc_vertices(list, 4);
8877  idx = nk_draw_list_alloc_elements(list, 6);
8878  if (!vtx || !idx) return;
8879 
8880  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8881  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8882  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8883 
8884  vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
8885  vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
8886  vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
8887  vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
8888 }
8889 
8890 NK_API void
8891 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
8892  struct nk_rect rect, struct nk_color color)
8893 {
8894  NK_ASSERT(list);
8895  if (!list) return;
8896  /* push new command with given texture */
8897  nk_draw_list_push_image(list, texture.handle);
8898  if (nk_image_is_subimage(&texture)) {
8899  /* add region inside of the texture */
8900  struct nk_vec2 uv[2];
8901  uv[0].x = (float)texture.region[0]/(float)texture.w;
8902  uv[0].y = (float)texture.region[1]/(float)texture.h;
8903  uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
8904  uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
8905  nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8906  nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
8907  } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8908  nk_vec2(rect.x + rect.w, rect.y + rect.h),
8909  nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
8910 }
8911 
8912 NK_API void
8913 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
8914  struct nk_rect rect, const char *text, int len, float font_height,
8915  struct nk_color fg)
8916 {
8917  float x = 0;
8918  int text_len = 0;
8919  nk_rune unicode = 0;
8920  nk_rune next = 0;
8921  int glyph_len = 0;
8922  int next_glyph_len = 0;
8923  struct nk_user_font_glyph g;
8924 
8925  NK_ASSERT(list);
8926  if (!list || !len || !text) return;
8927  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8928  list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
8929 
8930  nk_draw_list_push_image(list, font->texture);
8931  x = rect.x;
8932  glyph_len = nk_utf_decode(text, &unicode, len);
8933  if (!glyph_len) return;
8934 
8935  /* draw every glyph image */
8936  fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
8937  while (text_len < len && glyph_len) {
8938  float gx, gy, gh, gw;
8939  float char_width = 0;
8940  if (unicode == NK_UTF_INVALID) break;
8941 
8942  /* query currently drawn glyph information */
8943  next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
8944  font->query(font->userdata, font_height, &g, unicode,
8945  (next == NK_UTF_INVALID) ? '\0' : next);
8946 
8947  /* calculate and draw glyph drawing rectangle and image */
8948  gx = x + g.offset.x;
8949  gy = rect.y + g.offset.y;
8950  gw = g.width; gh = g.height;
8951  char_width = g.xadvance;
8952  nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
8953  g.uv[0], g.uv[1], fg);
8954 
8955  /* offset next glyph */
8956  text_len += glyph_len;
8957  x += char_width;
8958  glyph_len = next_glyph_len;
8959  unicode = next;
8960  }
8961 }
8962 
8963 NK_API nk_flags
8964 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
8965  struct nk_buffer *vertices, struct nk_buffer *elements,
8966  const struct nk_convert_config *config)
8967 {
8968  nk_flags res = NK_CONVERT_SUCCESS;
8969  const struct nk_command *cmd;
8970  NK_ASSERT(ctx);
8971  NK_ASSERT(cmds);
8972  NK_ASSERT(vertices);
8973  NK_ASSERT(elements);
8974  NK_ASSERT(config);
8975  NK_ASSERT(config->vertex_layout);
8976  NK_ASSERT(config->vertex_size);
8977  if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
8978  return NK_CONVERT_INVALID_PARAM;
8979 
8980  nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
8981  config->line_AA, config->shape_AA);
8982  nk_foreach(cmd, ctx)
8983  {
8984 #ifdef NK_INCLUDE_COMMAND_USERDATA
8985  ctx->draw_list.userdata = cmd->userdata;
8986 #endif
8987  switch (cmd->type) {
8988  case NK_COMMAND_NOP: break;
8989  case NK_COMMAND_SCISSOR: {
8990  const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
8991  nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
8992  } break;
8993  case NK_COMMAND_LINE: {
8994  const struct nk_command_line *l = (const struct nk_command_line*)cmd;
8995  nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
8996  nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
8997  } break;
8998  case NK_COMMAND_CURVE: {
8999  const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
9000  nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
9001  nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
9002  q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
9003  config->curve_segment_count, q->line_thickness);
9004  } break;
9005  case NK_COMMAND_RECT: {
9006  const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
9007  nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9008  r->color, (float)r->rounding, r->line_thickness);
9009  } break;
9010  case NK_COMMAND_RECT_FILLED: {
9011  const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
9012  nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9013  r->color, (float)r->rounding);
9014  } break;
9016  const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
9017  nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9018  r->left, r->top, r->right, r->bottom);
9019  } break;
9020  case NK_COMMAND_CIRCLE: {
9021  const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
9022  nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
9023  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
9024  config->circle_segment_count, c->line_thickness);
9025  } break;
9026  case NK_COMMAND_CIRCLE_FILLED: {
9027  const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
9028  nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
9029  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
9030  config->circle_segment_count);
9031  } break;
9032  case NK_COMMAND_ARC: {
9033  const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
9034  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
9035  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
9036  c->a[0], c->a[1], config->arc_segment_count);
9037  nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
9038  } break;
9039  case NK_COMMAND_ARC_FILLED: {
9040  const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
9041  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
9042  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
9043  c->a[0], c->a[1], config->arc_segment_count);
9044  nk_draw_list_path_fill(&ctx->draw_list, c->color);
9045  } break;
9046  case NK_COMMAND_TRIANGLE: {
9047  const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
9048  nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
9049  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
9050  t->line_thickness);
9051  } break;
9053  const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
9054  nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
9055  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
9056  } break;
9057  case NK_COMMAND_POLYGON: {
9058  int i;
9059  const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
9060  for (i = 0; i < p->point_count; ++i) {
9061  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9062  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9063  }
9064  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
9065  } break;
9067  int i;
9068  const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
9069  for (i = 0; i < p->point_count; ++i) {
9070  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9071  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9072  }
9073  nk_draw_list_path_fill(&ctx->draw_list, p->color);
9074  } break;
9075  case NK_COMMAND_POLYLINE: {
9076  int i;
9077  const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
9078  for (i = 0; i < p->point_count; ++i) {
9079  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9080  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9081  }
9082  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
9083  } break;
9084  case NK_COMMAND_TEXT: {
9085  const struct nk_command_text *t = (const struct nk_command_text*)cmd;
9086  nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
9087  t->string, t->length, t->height, t->foreground);
9088  } break;
9089  case NK_COMMAND_IMAGE: {
9090  const struct nk_command_image *i = (const struct nk_command_image*)cmd;
9091  nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
9092  } break;
9093  case NK_COMMAND_CUSTOM: {
9094  const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
9095  c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
9096  } break;
9097  default: break;
9098  }
9099  }
9100  res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
9101  res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
9102  res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
9103  return res;
9104 }
9105 NK_API const struct nk_draw_command*
9106 nk__draw_begin(const struct nk_context *ctx,
9107  const struct nk_buffer *buffer)
9108 {return nk__draw_list_begin(&ctx->draw_list, buffer);}
9109 
9110 NK_API const struct nk_draw_command*
9111 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
9112 {return nk__draw_list_end(&ctx->draw_list, buffer);}
9113 
9114 NK_API const struct nk_draw_command*
9115 nk__draw_next(const struct nk_draw_command *cmd,
9116  const struct nk_buffer *buffer, const struct nk_context *ctx)
9117 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);}
9118 
9119 #endif
9120 
9121 /*
9122  * ==============================================================
9123  *
9124  * FONT HANDLING
9125  *
9126  * ===============================================================
9127  */
9128 #ifdef NK_INCLUDE_FONT_BAKING
9129 /* -------------------------------------------------------------
9130  *
9131  * RECT PACK
9132  *
9133  * --------------------------------------------------------------*/
9134 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
9135 /* Sean Barrett 2014 */
9136 #define NK_RP__MAXVAL 0xffff
9137 typedef unsigned short nk_rp_coord;
9138 
9139 struct nk_rp_rect {
9140  /* reserved for your use: */
9141  int id;
9142  /* input: */
9143  nk_rp_coord w, h;
9144  /* output: */
9145  nk_rp_coord x, y;
9146  int was_packed;
9147  /* non-zero if valid packing */
9148 }; /* 16 bytes, nominally */
9149 
9150 struct nk_rp_node {
9151  nk_rp_coord x,y;
9152  struct nk_rp_node *next;
9153 };
9154 
9155 struct nk_rp_context {
9156  int width;
9157  int height;
9158  int align;
9159  int init_mode;
9160  int heuristic;
9161  int num_nodes;
9162  struct nk_rp_node *active_head;
9163  struct nk_rp_node *free_head;
9164  struct nk_rp_node extra[2];
9165  /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
9166 };
9167 
9168 struct nk_rp__findresult {
9169  int x,y;
9170  struct nk_rp_node **prev_link;
9171 };
9172 
9173 enum NK_RP_HEURISTIC {
9174  NK_RP_HEURISTIC_Skyline_default=0,
9175  NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
9176  NK_RP_HEURISTIC_Skyline_BF_sortHeight
9177 };
9178 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
9179 
9180 NK_INTERN void
9181 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
9182 {
9183  if (allow_out_of_mem)
9184  /* if it's ok to run out of memory, then don't bother aligning them; */
9185  /* this gives better packing, but may fail due to OOM (even though */
9186  /* the rectangles easily fit). @TODO a smarter approach would be to only */
9187  /* quantize once we've hit OOM, then we could get rid of this parameter. */
9188  context->align = 1;
9189  else {
9190  /* if it's not ok to run out of memory, then quantize the widths */
9191  /* so that num_nodes is always enough nodes. */
9192  /* */
9193  /* I.e. num_nodes * align >= width */
9194  /* align >= width / num_nodes */
9195  /* align = ceil(width/num_nodes) */
9196  context->align = (context->width + context->num_nodes-1) / context->num_nodes;
9197  }
9198 }
9199 
9200 NK_INTERN void
9201 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
9202  struct nk_rp_node *nodes, int num_nodes)
9203 {
9204  int i;
9205 #ifndef STBRP_LARGE_RECTS
9206  NK_ASSERT(width <= 0xffff && height <= 0xffff);
9207 #endif
9208 
9209  for (i=0; i < num_nodes-1; ++i)
9210  nodes[i].next = &nodes[i+1];
9211  nodes[i].next = 0;
9212  context->init_mode = NK_RP__INIT_skyline;
9213  context->heuristic = NK_RP_HEURISTIC_Skyline_default;
9214  context->free_head = &nodes[0];
9215  context->active_head = &context->extra[0];
9216  context->width = width;
9217  context->height = height;
9218  context->num_nodes = num_nodes;
9219  nk_rp_setup_allow_out_of_mem(context, 0);
9220 
9221  /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
9222  context->extra[0].x = 0;
9223  context->extra[0].y = 0;
9224  context->extra[0].next = &context->extra[1];
9225  context->extra[1].x = (nk_rp_coord) width;
9226  context->extra[1].y = 65535;
9227  context->extra[1].next = 0;
9228 }
9229 
9230 /* find minimum y position if it starts at x1 */
9231 NK_INTERN int
9232 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
9233  int x0, int width, int *pwaste)
9234 {
9235  struct nk_rp_node *node = first;
9236  int x1 = x0 + width;
9237  int min_y, visited_width, waste_area;
9238  NK_ASSERT(first->x <= x0);
9239  NK_UNUSED(c);
9240 
9241  NK_ASSERT(node->next->x > x0);
9242  /* we ended up handling this in the caller for efficiency */
9243  NK_ASSERT(node->x <= x0);
9244 
9245  min_y = 0;
9246  waste_area = 0;
9247  visited_width = 0;
9248  while (node->x < x1)
9249  {
9250  if (node->y > min_y) {
9251  /* raise min_y higher. */
9252  /* we've accounted for all waste up to min_y, */
9253  /* but we'll now add more waste for everything we've visited */
9254  waste_area += visited_width * (node->y - min_y);
9255  min_y = node->y;
9256  /* the first time through, visited_width might be reduced */
9257  if (node->x < x0)
9258  visited_width += node->next->x - x0;
9259  else
9260  visited_width += node->next->x - node->x;
9261  } else {
9262  /* add waste area */
9263  int under_width = node->next->x - node->x;
9264  if (under_width + visited_width > width)
9265  under_width = width - visited_width;
9266  waste_area += under_width * (min_y - node->y);
9267  visited_width += under_width;
9268  }
9269  node = node->next;
9270  }
9271  *pwaste = waste_area;
9272  return min_y;
9273 }
9274 
9275 NK_INTERN struct nk_rp__findresult
9276 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
9277 {
9278  int best_waste = (1<<30), best_x, best_y = (1 << 30);
9279  struct nk_rp__findresult fr;
9280  struct nk_rp_node **prev, *node, *tail, **best = 0;
9281 
9282  /* align to multiple of c->align */
9283  width = (width + c->align - 1);
9284  width -= width % c->align;
9285  NK_ASSERT(width % c->align == 0);
9286 
9287  node = c->active_head;
9288  prev = &c->active_head;
9289  while (node->x + width <= c->width) {
9290  int y,waste;
9291  y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
9292  /* actually just want to test BL */
9293  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
9294  /* bottom left */
9295  if (y < best_y) {
9296  best_y = y;
9297  best = prev;
9298  }
9299  } else {
9300  /* best-fit */
9301  if (y + height <= c->height) {
9302  /* can only use it if it first vertically */
9303  if (y < best_y || (y == best_y && waste < best_waste)) {
9304  best_y = y;
9305  best_waste = waste;
9306  best = prev;
9307  }
9308  }
9309  }
9310  prev = &node->next;
9311  node = node->next;
9312  }
9313  best_x = (best == 0) ? 0 : (*best)->x;
9314 
9315  /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
9316  /* */
9317  /* e.g, if fitting */
9318  /* */
9319  /* ____________________ */
9320  /* |____________________| */
9321  /* */
9322  /* into */
9323  /* */
9324  /* | | */
9325  /* | ____________| */
9326  /* |____________| */
9327  /* */
9328  /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
9329  /* */
9330  /* This makes BF take about 2x the time */
9331  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
9332  {
9333  tail = c->active_head;
9334  node = c->active_head;
9335  prev = &c->active_head;
9336  /* find first node that's admissible */
9337  while (tail->x < width)
9338  tail = tail->next;
9339  while (tail)
9340  {
9341  int xpos = tail->x - width;
9342  int y,waste;
9343  NK_ASSERT(xpos >= 0);
9344  /* find the left position that matches this */
9345  while (node->next->x <= xpos) {
9346  prev = &node->next;
9347  node = node->next;
9348  }
9349  NK_ASSERT(node->next->x > xpos && node->x <= xpos);
9350  y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
9351  if (y + height < c->height) {
9352  if (y <= best_y) {
9353  if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
9354  best_x = xpos;
9355  NK_ASSERT(y <= best_y);
9356  best_y = y;
9357  best_waste = waste;
9358  best = prev;
9359  }
9360  }
9361  }
9362  tail = tail->next;
9363  }
9364  }
9365  fr.prev_link = best;
9366  fr.x = best_x;
9367  fr.y = best_y;
9368  return fr;
9369 }
9370 
9371 NK_INTERN struct nk_rp__findresult
9372 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
9373 {
9374  /* find best position according to heuristic */
9375  struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
9376  struct nk_rp_node *node, *cur;
9377 
9378  /* bail if: */
9379  /* 1. it failed */
9380  /* 2. the best node doesn't fit (we don't always check this) */
9381  /* 3. we're out of memory */
9382  if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
9383  res.prev_link = 0;
9384  return res;
9385  }
9386 
9387  /* on success, create new node */
9388  node = context->free_head;
9389  node->x = (nk_rp_coord) res.x;
9390  node->y = (nk_rp_coord) (res.y + height);
9391 
9392  context->free_head = node->next;
9393 
9394  /* insert the new node into the right starting point, and */
9395  /* let 'cur' point to the remaining nodes needing to be */
9396  /* stitched back in */
9397  cur = *res.prev_link;
9398  if (cur->x < res.x) {
9399  /* preserve the existing one, so start testing with the next one */
9400  struct nk_rp_node *next = cur->next;
9401  cur->next = node;
9402  cur = next;
9403  } else {
9404  *res.prev_link = node;
9405  }
9406 
9407  /* from here, traverse cur and free the nodes, until we get to one */
9408  /* that shouldn't be freed */
9409  while (cur->next && cur->next->x <= res.x + width) {
9410  struct nk_rp_node *next = cur->next;
9411  /* move the current node to the free list */
9412  cur->next = context->free_head;
9413  context->free_head = cur;
9414  cur = next;
9415  }
9416  /* stitch the list back in */
9417  node->next = cur;
9418 
9419  if (cur->x < res.x + width)
9420  cur->x = (nk_rp_coord) (res.x + width);
9421  return res;
9422 }
9423 
9424 NK_INTERN int
9425 nk_rect_height_compare(const void *a, const void *b)
9426 {
9427  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9428  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9429  if (p->h > q->h)
9430  return -1;
9431  if (p->h < q->h)
9432  return 1;
9433  return (p->w > q->w) ? -1 : (p->w < q->w);
9434 }
9435 
9436 NK_INTERN int
9437 nk_rect_original_order(const void *a, const void *b)
9438 {
9439  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9440  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9441  return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
9442 }
9443 
9444 NK_INTERN void
9445 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
9446 {
9447  /* iterative quick sort */
9448  #define NK_MAX_SORT_STACK 64
9449  unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
9450  unsigned seed = len/2 * 69069+1;
9451  for (;;) {
9452  for (; left+1 < len; len++) {
9453  struct nk_rp_rect pivot, tmp;
9454  if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
9455  pivot = array[left+seed%(len-left)];
9456  seed = seed * 69069 + 1;
9457  stack[pos++] = len;
9458  for (right = left-1;;) {
9459  while (cmp(&array[++right], &pivot) < 0);
9460  while (cmp(&pivot, &array[--len]) < 0);
9461  if (right >= len) break;
9462  tmp = array[right];
9463  array[right] = array[len];
9464  array[len] = tmp;
9465  }
9466  }
9467  if (pos == 0) break;
9468  left = len;
9469  len = stack[--pos];
9470  }
9471  #undef NK_MAX_SORT_STACK
9472 }
9473 
9474 NK_INTERN void
9475 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
9476 {
9477  int i;
9478  /* we use the 'was_packed' field internally to allow sorting/unsorting */
9479  for (i=0; i < num_rects; ++i) {
9480  rects[i].was_packed = i;
9481  }
9482 
9483  /* sort according to heuristic */
9484  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
9485 
9486  for (i=0; i < num_rects; ++i) {
9487  struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
9488  if (fr.prev_link) {
9489  rects[i].x = (nk_rp_coord) fr.x;
9490  rects[i].y = (nk_rp_coord) fr.y;
9491  } else {
9492  rects[i].x = rects[i].y = NK_RP__MAXVAL;
9493  }
9494  }
9495 
9496  /* unsort */
9497  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
9498 
9499  /* set was_packed flags */
9500  for (i=0; i < num_rects; ++i)
9501  rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
9502 }
9503 
9504 /*
9505  * ==============================================================
9506  *
9507  * TRUETYPE
9508  *
9509  * ===============================================================
9510  */
9511 /* stb_truetype.h - v1.07 - public domain */
9512 #define NK_TT_MAX_OVERSAMPLE 8
9513 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1)
9514 
9515 struct nk_tt_bakedchar {
9516  unsigned short x0,y0,x1,y1;
9517  /* coordinates of bbox in bitmap */
9518  float xoff,yoff,xadvance;
9519 };
9520 
9521 struct nk_tt_aligned_quad{
9522  float x0,y0,s0,t0; /* top-left */
9523  float x1,y1,s1,t1; /* bottom-right */
9524 };
9525 
9526 struct nk_tt_packedchar {
9527  unsigned short x0,y0,x1,y1;
9528  /* coordinates of bbox in bitmap */
9529  float xoff,yoff,xadvance;
9530  float xoff2,yoff2;
9531 };
9532 
9533 struct nk_tt_pack_range {
9534  float font_size;
9535  int first_unicode_codepoint_in_range;
9536  /* if non-zero, then the chars are continuous, and this is the first codepoint */
9537  int *array_of_unicode_codepoints;
9538  /* if non-zero, then this is an array of unicode codepoints */
9539  int num_chars;
9540  struct nk_tt_packedchar *chardata_for_range; /* output */
9541  unsigned char h_oversample, v_oversample;
9542  /* don't set these, they're used internally */
9543 };
9544 
9545 struct nk_tt_pack_context {
9546  void *pack_info;
9547  int width;
9548  int height;
9549  int stride_in_bytes;
9550  int padding;
9551  unsigned int h_oversample, v_oversample;
9552  unsigned char *pixels;
9553  void *nodes;
9554 };
9555 
9556 struct nk_tt_fontinfo {
9557  const unsigned char* data; /* pointer to .ttf file */
9558  int fontstart;/* offset of start of font */
9559  int numGlyphs;/* number of glyphs, needed for range checking */
9560  int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
9561  int index_map; /* a cmap mapping for our chosen character encoding */
9562  int indexToLocFormat; /* format needed to map from glyph index to glyph */
9563 };
9564 
9565 enum {
9566  NK_TT_vmove=1,
9567  NK_TT_vline,
9568  NK_TT_vcurve
9569 };
9570 
9571 struct nk_tt_vertex {
9572  short x,y,cx,cy;
9573  unsigned char type,padding;
9574 };
9575 
9576 struct nk_tt__bitmap{
9577  int w,h,stride;
9578  unsigned char *pixels;
9579 };
9580 
9581 struct nk_tt__hheap_chunk {
9582  struct nk_tt__hheap_chunk *next;
9583 };
9584 struct nk_tt__hheap {
9585  struct nk_allocator alloc;
9586  struct nk_tt__hheap_chunk *head;
9587  void *first_free;
9588  int num_remaining_in_head_chunk;
9589 };
9590 
9591 struct nk_tt__edge {
9592  float x0,y0, x1,y1;
9593  int invert;
9594 };
9595 
9596 struct nk_tt__active_edge {
9597  struct nk_tt__active_edge *next;
9598  float fx,fdx,fdy;
9599  float direction;
9600  float sy;
9601  float ey;
9602 };
9603 struct nk_tt__point {float x,y;};
9604 
9605 #define NK_TT_MACSTYLE_DONTCARE 0
9606 #define NK_TT_MACSTYLE_BOLD 1
9607 #define NK_TT_MACSTYLE_ITALIC 2
9608 #define NK_TT_MACSTYLE_UNDERSCORE 4
9609 #define NK_TT_MACSTYLE_NONE 8
9610 /* <= not same as 0, this makes us check the bitfield is 0 */
9611 
9612 enum { /* platformID */
9613  NK_TT_PLATFORM_ID_UNICODE =0,
9614  NK_TT_PLATFORM_ID_MAC =1,
9615  NK_TT_PLATFORM_ID_ISO =2,
9616  NK_TT_PLATFORM_ID_MICROSOFT =3
9617 };
9618 
9619 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
9620  NK_TT_UNICODE_EID_UNICODE_1_0 =0,
9621  NK_TT_UNICODE_EID_UNICODE_1_1 =1,
9622  NK_TT_UNICODE_EID_ISO_10646 =2,
9623  NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
9624  NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
9625 };
9626 
9627 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
9628  NK_TT_MS_EID_SYMBOL =0,
9629  NK_TT_MS_EID_UNICODE_BMP =1,
9630  NK_TT_MS_EID_SHIFTJIS =2,
9631  NK_TT_MS_EID_UNICODE_FULL =10
9632 };
9633 
9634 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
9635  NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4,
9636  NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5,
9637  NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6,
9638  NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7
9639 };
9640 
9641 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
9642  /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
9643  NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410,
9644  NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411,
9645  NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412,
9646  NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419,
9647  NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409,
9648  NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D
9649 };
9650 
9651 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
9652  NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11,
9653  NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23,
9654  NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32,
9655  NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 ,
9656  NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 ,
9657  NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
9658  NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19
9659 };
9660 
9661 #define nk_ttBYTE(p) (* (const nk_byte *) (p))
9662 #define nk_ttCHAR(p) (* (const char *) (p))
9663 
9664 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
9665  #define nk_ttUSHORT(p) (* (nk_ushort *) (p))
9666  #define nk_ttSHORT(p) (* (nk_short *) (p))
9667  #define nk_ttULONG(p) (* (nk_uint *) (p))
9668  #define nk_ttLONG(p) (* (nk_int *) (p))
9669 #else
9670  static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
9671  static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); }
9672  static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
9673 #endif
9674 
9675 #define nk_tt_tag4(p,c0,c1,c2,c3)\
9676  ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
9677 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
9678 
9679 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9680  int glyph_index, struct nk_tt_vertex **pvertices);
9681 
9682 NK_INTERN nk_uint
9683 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
9684 {
9685  /* @OPTIMIZE: binary search */
9686  nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
9687  nk_uint tabledir = fontstart + 12;
9688  nk_int i;
9689  for (i = 0; i < num_tables; ++i) {
9690  nk_uint loc = tabledir + (nk_uint)(16*i);
9691  if (nk_tt_tag(data+loc+0, tag))
9692  return nk_ttULONG(data+loc+8);
9693  }
9694  return 0;
9695 }
9696 
9697 NK_INTERN int
9698 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
9699 {
9700  nk_uint cmap, t;
9701  nk_int i,numTables;
9702  const nk_byte *data = (const nk_byte *) data2;
9703 
9704  info->data = data;
9705  info->fontstart = fontstart;
9706 
9707  cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */
9708  info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
9709  info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
9710  info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
9711  info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
9712  info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
9713  info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
9714  if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
9715  return 0;
9716 
9717  t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
9718  if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
9719  else info->numGlyphs = 0xffff;
9720 
9721  /* find a cmap encoding table we understand *now* to avoid searching */
9722  /* later. (todo: could make this installable) */
9723  /* the same regardless of glyph. */
9724  numTables = nk_ttUSHORT(data + cmap + 2);
9725  info->index_map = 0;
9726  for (i=0; i < numTables; ++i)
9727  {
9728  nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
9729  /* find an encoding we understand: */
9730  switch(nk_ttUSHORT(data+encoding_record)) {
9731  case NK_TT_PLATFORM_ID_MICROSOFT:
9732  switch (nk_ttUSHORT(data+encoding_record+2)) {
9733  case NK_TT_MS_EID_UNICODE_BMP:
9734  case NK_TT_MS_EID_UNICODE_FULL:
9735  /* MS/Unicode */
9736  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9737  break;
9738  default: break;
9739  } break;
9740  case NK_TT_PLATFORM_ID_UNICODE:
9741  /* Mac/iOS has these */
9742  /* all the encodingIDs are unicode, so we don't bother to check it */
9743  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9744  break;
9745  default: break;
9746  }
9747  }
9748  if (info->index_map == 0)
9749  return 0;
9750  info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
9751  return 1;
9752 }
9753 
9754 NK_INTERN int
9755 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
9756 {
9757  const nk_byte *data = info->data;
9758  nk_uint index_map = (nk_uint)info->index_map;
9759 
9760  nk_ushort format = nk_ttUSHORT(data + index_map + 0);
9761  if (format == 0) { /* apple byte encoding */
9762  nk_int bytes = nk_ttUSHORT(data + index_map + 2);
9763  if (unicode_codepoint < bytes-6)
9764  return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
9765  return 0;
9766  } else if (format == 6) {
9767  nk_uint first = nk_ttUSHORT(data + index_map + 6);
9768  nk_uint count = nk_ttUSHORT(data + index_map + 8);
9769  if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
9770  return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
9771  return 0;
9772  } else if (format == 2) {
9773  NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
9774  return 0;
9775  } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
9776  nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
9777  nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
9778  nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
9779  nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
9780 
9781  /* do a binary search of the segments */
9782  nk_uint endCount = index_map + 14;
9783  nk_uint search = endCount;
9784 
9785  if (unicode_codepoint > 0xffff)
9786  return 0;
9787 
9788  /* they lie from endCount .. endCount + segCount */
9789  /* but searchRange is the nearest power of two, so... */
9790  if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
9791  search += (nk_uint)(rangeShift*2);
9792 
9793  /* now decrement to bias correctly to find smallest */
9794  search -= 2;
9795  while (entrySelector) {
9796  nk_ushort end;
9797  searchRange >>= 1;
9798  end = nk_ttUSHORT(data + search + searchRange*2);
9799  if (unicode_codepoint > end)
9800  search += (nk_uint)(searchRange*2);
9801  --entrySelector;
9802  }
9803  search += 2;
9804 
9805  {
9806  nk_ushort offset, start;
9807  nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
9808 
9809  NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
9810  start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
9811  if (unicode_codepoint < start)
9812  return 0;
9813 
9814  offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
9815  if (offset == 0)
9816  return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
9817 
9818  return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
9819  }
9820  } else if (format == 12 || format == 13) {
9821  nk_uint ngroups = nk_ttULONG(data+index_map+12);
9822  nk_int low,high;
9823  low = 0; high = (nk_int)ngroups;
9824  /* Binary search the right group. */
9825  while (low < high) {
9826  nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
9827  nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
9828  nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
9829  if ((nk_uint) unicode_codepoint < start_char)
9830  high = mid;
9831  else if ((nk_uint) unicode_codepoint > end_char)
9832  low = mid+1;
9833  else {
9834  nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
9835  if (format == 12)
9836  return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
9837  else /* format == 13 */
9838  return (int)start_glyph;
9839  }
9840  }
9841  return 0; /* not found */
9842  }
9843  /* @TODO */
9844  NK_ASSERT(0);
9845  return 0;
9846 }
9847 
9848 NK_INTERN void
9849 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
9850 {
9851  v->type = type;
9852  v->x = (nk_short) x;
9853  v->y = (nk_short) y;
9854  v->cx = (nk_short) cx;
9855  v->cy = (nk_short) cy;
9856 }
9857 
9858 NK_INTERN int
9859 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
9860 {
9861  int g1,g2;
9862  if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
9863  if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
9864 
9865  if (info->indexToLocFormat == 0) {
9866  g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
9867  g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
9868  } else {
9869  g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
9870  g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
9871  }
9872  return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
9873 }
9874 
9875 NK_INTERN int
9876 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
9877  int *x0, int *y0, int *x1, int *y1)
9878 {
9879  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9880  if (g < 0) return 0;
9881 
9882  if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
9883  if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
9884  if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
9885  if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
9886  return 1;
9887 }
9888 
9889 NK_INTERN int
9890 stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
9891  int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
9892 {
9893  if (start_off) {
9894  if (was_off)
9895  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
9896  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
9897  } else {
9898  if (was_off)
9899  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
9900  else
9901  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
9902  }
9903  return num_vertices;
9904 }
9905 
9906 NK_INTERN int
9907 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9908  int glyph_index, struct nk_tt_vertex **pvertices)
9909 {
9910  nk_short numberOfContours;
9911  const nk_byte *endPtsOfContours;
9912  const nk_byte *data = info->data;
9913  struct nk_tt_vertex *vertices=0;
9914  int num_vertices=0;
9915  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9916  *pvertices = 0;
9917 
9918  if (g < 0) return 0;
9919  numberOfContours = nk_ttSHORT(data + g);
9920  if (numberOfContours > 0) {
9921  nk_byte flags=0,flagcount;
9922  nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
9923  nk_int x,y,cx,cy,sx,sy, scx,scy;
9924  const nk_byte *points;
9925  endPtsOfContours = (data + g + 10);
9926  ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
9927  points = data + g + 10 + numberOfContours * 2 + 2 + ins;
9928 
9929  n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
9930  m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
9931  vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
9932  if (vertices == 0)
9933  return 0;
9934 
9935  next_move = 0;
9936  flagcount=0;
9937 
9938  /* in first pass, we load uninterpreted data into the allocated array */
9939  /* above, shifted to the end of the array so we won't overwrite it when */
9940  /* we create our final data starting from the front */
9941  off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
9942 
9943  /* first load flags */
9944  for (i=0; i < n; ++i) {
9945  if (flagcount == 0) {
9946  flags = *points++;
9947  if (flags & 8)
9948  flagcount = *points++;
9949  } else --flagcount;
9950  vertices[off+i].type = flags;
9951  }
9952 
9953  /* now load x coordinates */
9954  x=0;
9955  for (i=0; i < n; ++i) {
9956  flags = vertices[off+i].type;
9957  if (flags & 2) {
9958  nk_short dx = *points++;
9959  x += (flags & 16) ? dx : -dx; /* ??? */
9960  } else {
9961  if (!(flags & 16)) {
9962  x = x + (nk_short) (points[0]*256 + points[1]);
9963  points += 2;
9964  }
9965  }
9966  vertices[off+i].x = (nk_short) x;
9967  }
9968 
9969  /* now load y coordinates */
9970  y=0;
9971  for (i=0; i < n; ++i) {
9972  flags = vertices[off+i].type;
9973  if (flags & 4) {
9974  nk_short dy = *points++;
9975  y += (flags & 32) ? dy : -dy; /* ??? */
9976  } else {
9977  if (!(flags & 32)) {
9978  y = y + (nk_short) (points[0]*256 + points[1]);
9979  points += 2;
9980  }
9981  }
9982  vertices[off+i].y = (nk_short) y;
9983  }
9984 
9985  /* now convert them to our format */
9986  num_vertices=0;
9987  sx = sy = cx = cy = scx = scy = 0;
9988  for (i=0; i < n; ++i)
9989  {
9990  flags = vertices[off+i].type;
9991  x = (nk_short) vertices[off+i].x;
9992  y = (nk_short) vertices[off+i].y;
9993 
9994  if (next_move == i) {
9995  if (i != 0)
9996  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
9997 
9998  /* now start the new one */
9999  start_off = !(flags & 1);
10000  if (start_off) {
10001  /* if we start off with an off-curve point, then when we need to find a point on the curve */
10002  /* where we can start, and we need to save some state for when we wraparound. */
10003  scx = x;
10004  scy = y;
10005  if (!(vertices[off+i+1].type & 1)) {
10006  /* next point is also a curve point, so interpolate an on-point curve */
10007  sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
10008  sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
10009  } else {
10010  /* otherwise just use the next point as our start point */
10011  sx = (nk_int) vertices[off+i+1].x;
10012  sy = (nk_int) vertices[off+i+1].y;
10013  ++i; /* we're using point i+1 as the starting point, so skip it */
10014  }
10015  } else {
10016  sx = x;
10017  sy = y;
10018  }
10019  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
10020  was_off = 0;
10021  next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
10022  ++j;
10023  } else {
10024  if (!(flags & 1))
10025  { /* if it's a curve */
10026  if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
10027  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
10028  cx = x;
10029  cy = y;
10030  was_off = 1;
10031  } else {
10032  if (was_off)
10033  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
10034  else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
10035  was_off = 0;
10036  }
10037  }
10038  }
10039  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
10040  } else if (numberOfContours == -1) {
10041  /* Compound shapes. */
10042  int more = 1;
10043  const nk_byte *comp = data + g + 10;
10044  num_vertices = 0;
10045  vertices = 0;
10046 
10047  while (more)
10048  {
10049  nk_ushort flags, gidx;
10050  int comp_num_verts = 0, i;
10051  struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
10052  float mtx[6] = {1,0,0,1,0,0}, m, n;
10053 
10054  flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
10055  gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
10056 
10057  if (flags & 2) { /* XY values */
10058  if (flags & 1) { /* shorts */
10059  mtx[4] = nk_ttSHORT(comp); comp+=2;
10060  mtx[5] = nk_ttSHORT(comp); comp+=2;
10061  } else {
10062  mtx[4] = nk_ttCHAR(comp); comp+=1;
10063  mtx[5] = nk_ttCHAR(comp); comp+=1;
10064  }
10065  } else {
10066  /* @TODO handle matching point */
10067  NK_ASSERT(0);
10068  }
10069  if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
10070  mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10071  mtx[1] = mtx[2] = 0;
10072  } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
10073  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10074  mtx[1] = mtx[2] = 0;
10075  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10076  } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
10077  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10078  mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10079  mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10080  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10081  }
10082 
10083  /* Find transformation scales. */
10084  m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
10085  n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
10086 
10087  /* Get indexed glyph. */
10088  comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
10089  if (comp_num_verts > 0)
10090  {
10091  /* Transform vertices. */
10092  for (i = 0; i < comp_num_verts; ++i) {
10093  struct nk_tt_vertex* v = &comp_verts[i];
10094  short x,y;
10095  x=v->x; y=v->y;
10096  v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
10097  v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
10098  x=v->cx; y=v->cy;
10099  v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
10100  v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
10101  }
10102  /* Append vertices. */
10103  tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
10104  (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
10105  if (!tmp) {
10106  if (vertices) alloc->free(alloc->userdata, vertices);
10107  if (comp_verts) alloc->free(alloc->userdata, comp_verts);
10108  return 0;
10109  }
10110  if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
10111  NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
10112  if (vertices) alloc->free(alloc->userdata,vertices);
10113  vertices = tmp;
10114  alloc->free(alloc->userdata,comp_verts);
10115  num_vertices += comp_num_verts;
10116  }
10117  /* More components ? */
10118  more = flags & (1<<5);
10119  }
10120  } else if (numberOfContours < 0) {
10121  /* @TODO other compound variations? */
10122  NK_ASSERT(0);
10123  } else {
10124  /* numberOfCounters == 0, do nothing */
10125  }
10126  *pvertices = vertices;
10127  return num_vertices;
10128 }
10129 
10130 NK_INTERN void
10131 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
10132  int *advanceWidth, int *leftSideBearing)
10133 {
10134  nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
10135  if (glyph_index < numOfLongHorMetrics) {
10136  if (advanceWidth)
10137  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
10138  if (leftSideBearing)
10139  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
10140  } else {
10141  if (advanceWidth)
10142  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
10143  if (leftSideBearing)
10144  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
10145  }
10146 }
10147 
10148 NK_INTERN void
10149 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
10150  int *ascent, int *descent, int *lineGap)
10151 {
10152  if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4);
10153  if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
10154  if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
10155 }
10156 
10157 NK_INTERN float
10158 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
10159 {
10160  int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
10161  return (float) height / (float)fheight;
10162 }
10163 
10164 NK_INTERN float
10165 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
10166 {
10167  int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
10168  return pixels / (float)unitsPerEm;
10169 }
10170 
10171 /*-------------------------------------------------------------
10172  * antialiasing software rasterizer
10173  * --------------------------------------------------------------*/
10174 NK_INTERN void
10175 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
10176  int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
10177  int *ix0, int *iy0, int *ix1, int *iy1)
10178 {
10179  int x0,y0,x1,y1;
10180  if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
10181  /* e.g. space character */
10182  if (ix0) *ix0 = 0;
10183  if (iy0) *iy0 = 0;
10184  if (ix1) *ix1 = 0;
10185  if (iy1) *iy1 = 0;
10186  } else {
10187  /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
10188  if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
10189  if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
10190  if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
10191  if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
10192  }
10193 }
10194 
10195 NK_INTERN void
10196 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
10197  float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
10198 {
10199  nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
10200 }
10201 
10202 /*-------------------------------------------------------------
10203  * Rasterizer
10204  * --------------------------------------------------------------*/
10205 NK_INTERN void*
10206 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
10207 {
10208  if (hh->first_free) {
10209  void *p = hh->first_free;
10210  hh->first_free = * (void **) p;
10211  return p;
10212  } else {
10213  if (hh->num_remaining_in_head_chunk == 0) {
10214  int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
10215  struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
10216  hh->alloc.alloc(hh->alloc.userdata, 0,
10217  sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
10218  if (c == 0) return 0;
10219  c->next = hh->head;
10220  hh->head = c;
10221  hh->num_remaining_in_head_chunk = count;
10222  }
10223  --hh->num_remaining_in_head_chunk;
10224  return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
10225  }
10226 }
10227 
10228 NK_INTERN void
10229 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
10230 {
10231  *(void **) p = hh->first_free;
10232  hh->first_free = p;
10233 }
10234 
10235 NK_INTERN void
10236 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
10237 {
10238  struct nk_tt__hheap_chunk *c = hh->head;
10239  while (c) {
10240  struct nk_tt__hheap_chunk *n = c->next;
10241  hh->alloc.free(hh->alloc.userdata, c);
10242  c = n;
10243  }
10244 }
10245 
10246 NK_INTERN struct nk_tt__active_edge*
10247 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
10248  int off_x, float start_point)
10249 {
10250  struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
10251  nk_tt__hheap_alloc(hh, sizeof(*z));
10252  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
10253  /*STBTT_assert(e->y0 <= start_point); */
10254  if (!z) return z;
10255  z->fdx = dxdy;
10256  z->fdy = (dxdy != 0) ? (1/dxdy): 0;
10257  z->fx = e->x0 + dxdy * (start_point - e->y0);
10258  z->fx -= (float)off_x;
10259  z->direction = e->invert ? 1.0f : -1.0f;
10260  z->sy = e->y0;
10261  z->ey = e->y1;
10262  z->next = 0;
10263  return z;
10264 }
10265 
10266 NK_INTERN void
10267 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
10268  float x0, float y0, float x1, float y1)
10269 {
10270  if (y0 == y1) return;
10271  NK_ASSERT(y0 < y1);
10272  NK_ASSERT(e->sy <= e->ey);
10273  if (y0 > e->ey) return;
10274  if (y1 < e->sy) return;
10275  if (y0 < e->sy) {
10276  x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
10277  y0 = e->sy;
10278  }
10279  if (y1 > e->ey) {
10280  x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
10281  y1 = e->ey;
10282  }
10283 
10284  if (x0 == x) NK_ASSERT(x1 <= x+1);
10285  else if (x0 == x+1) NK_ASSERT(x1 >= x);
10286  else if (x0 <= x) NK_ASSERT(x1 <= x);
10287  else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
10288  else NK_ASSERT(x1 >= x && x1 <= x+1);
10289 
10290  if (x0 <= x && x1 <= x)
10291  scanline[x] += e->direction * (y1-y0);
10292  else if (x0 >= x+1 && x1 >= x+1);
10293  else {
10294  NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
10295  /* coverage = 1 - average x position */
10296  scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
10297  }
10298 }
10299 
10300 NK_INTERN void
10301 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
10302  struct nk_tt__active_edge *e, float y_top)
10303 {
10304  float y_bottom = y_top+1;
10305  while (e)
10306  {
10307  /* brute force every pixel */
10308  /* compute intersection points with top & bottom */
10309  NK_ASSERT(e->ey >= y_top);
10310  if (e->fdx == 0) {
10311  float x0 = e->fx;
10312  if (x0 < len) {
10313  if (x0 >= 0) {
10314  nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
10315  nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
10316  } else {
10317  nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
10318  }
10319  }
10320  } else {
10321  float x0 = e->fx;
10322  float dx = e->fdx;
10323  float xb = x0 + dx;
10324  float x_top, x_bottom;
10325  float y0,y1;
10326  float dy = e->fdy;
10327  NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
10328 
10329  /* compute endpoints of line segment clipped to this scanline (if the */
10330  /* line segment starts on this scanline. x0 is the intersection of the */
10331  /* line with y_top, but that may be off the line segment. */
10332  if (e->sy > y_top) {
10333  x_top = x0 + dx * (e->sy - y_top);
10334  y0 = e->sy;
10335  } else {
10336  x_top = x0;
10337  y0 = y_top;
10338  }
10339 
10340  if (e->ey < y_bottom) {
10341  x_bottom = x0 + dx * (e->ey - y_top);
10342  y1 = e->ey;
10343  } else {
10344  x_bottom = xb;
10345  y1 = y_bottom;
10346  }
10347 
10348  if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
10349  {
10350  /* from here on, we don't have to range check x values */
10351  if ((int) x_top == (int) x_bottom) {
10352  float height;
10353  /* simple case, only spans one pixel */
10354  int x = (int) x_top;
10355  height = y1 - y0;
10356  NK_ASSERT(x >= 0 && x < len);
10357  scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height;
10358  scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
10359  } else {
10360  int x,x1,x2;
10361  float y_crossing, step, sign, area;
10362  /* covers 2+ pixels */
10363  if (x_top > x_bottom)
10364  {
10365  /* flip scanline vertically; signed area is the same */
10366  float t;
10367  y0 = y_bottom - (y0 - y_top);
10368  y1 = y_bottom - (y1 - y_top);
10369  t = y0; y0 = y1; y1 = t;
10370  t = x_bottom; x_bottom = x_top; x_top = t;
10371  dx = -dx;
10372  dy = -dy;
10373  t = x0; x0 = xb; xb = t;
10374  }
10375 
10376  x1 = (int) x_top;
10377  x2 = (int) x_bottom;
10378  /* compute intersection with y axis at x1+1 */
10379  y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
10380 
10381  sign = e->direction;
10382  /* area of the rectangle covered from y0..y_crossing */
10383  area = sign * (y_crossing-y0);
10384  /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
10385  scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
10386 
10387  step = sign * dy;
10388  for (x = x1+1; x < x2; ++x) {
10389  scanline[x] += area + step/2;
10390  area += step;
10391  }
10392  y_crossing += (float)dy * (float)(x2 - (x1+1));
10393 
10394  scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
10395  scanline_fill[x2] += sign * (y1-y0);
10396  }
10397  }
10398  else
10399  {
10400  /* if edge goes outside of box we're drawing, we require */
10401  /* clipping logic. since this does not match the intended use */
10402  /* of this library, we use a different, very slow brute */
10403  /* force implementation */
10404  int x;
10405  for (x=0; x < len; ++x)
10406  {
10407  /* cases: */
10408  /* */
10409  /* there can be up to two intersections with the pixel. any intersection */
10410  /* with left or right edges can be handled by splitting into two (or three) */
10411  /* regions. intersections with top & bottom do not necessitate case-wise logic. */
10412  /* */
10413  /* the old way of doing this found the intersections with the left & right edges, */
10414  /* then used some simple logic to produce up to three segments in sorted order */
10415  /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
10416  /* across the x border, then the corresponding y position might not be distinct */
10417  /* from the other y segment, and it might ignored as an empty segment. to avoid */
10418  /* that, we need to explicitly produce segments based on x positions. */
10419 
10420  /* rename variables to clear pairs */
10421  float ya = y_top;
10422  float x1 = (float) (x);
10423  float x2 = (float) (x+1);
10424  float x3 = xb;
10425  float y3 = y_bottom;
10426  float yb,y2;
10427 
10428  yb = ((float)x - x0) / dx + y_top;
10429  y2 = ((float)x+1 - x0) / dx + y_top;
10430 
10431  if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
10432  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10433  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
10434  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10435  } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
10436  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10437  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
10438  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10439  } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
10440  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10441  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10442  } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
10443  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10444  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10445  } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
10446  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10447  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10448  } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
10449  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10450  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10451  } else { /* one segment */
10452  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
10453  }
10454  }
10455  }
10456  }
10457  e = e->next;
10458  }
10459 }
10460 
10461 /* directly AA rasterize edges w/o supersampling */
10462 NK_INTERN void
10463 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
10464  int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
10465 {
10466  struct nk_tt__hheap hh;
10467  struct nk_tt__active_edge *active = 0;
10468  int y,j=0, i;
10469  float scanline_data[129], *scanline, *scanline2;
10470 
10471  NK_UNUSED(vsubsample);
10472  nk_zero_struct(hh);
10473  hh.alloc = *alloc;
10474 
10475  if (result->w > 64)
10476  scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
10477  else scanline = scanline_data;
10478 
10479  scanline2 = scanline + result->w;
10480  y = off_y;
10481  e[n].y0 = (float) (off_y + result->h) + 1;
10482 
10483  while (j < result->h)
10484  {
10485  /* find center of pixel for this scanline */
10486  float scan_y_top = (float)y + 0.0f;
10487  float scan_y_bottom = (float)y + 1.0f;
10488  struct nk_tt__active_edge **step = &active;
10489 
10490  NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
10491  NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
10492 
10493  /* update all active edges; */
10494  /* remove all active edges that terminate before the top of this scanline */
10495  while (*step) {
10496  struct nk_tt__active_edge * z = *step;
10497  if (z->ey <= scan_y_top) {
10498  *step = z->next; /* delete from list */
10499  NK_ASSERT(z->direction);
10500  z->direction = 0;
10501  nk_tt__hheap_free(&hh, z);
10502  } else {
10503  step = &((*step)->next); /* advance through list */
10504  }
10505  }
10506 
10507  /* insert all edges that start before the bottom of this scanline */
10508  while (e->y0 <= scan_y_bottom) {
10509  if (e->y0 != e->y1) {
10510  struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
10511  if (z != 0) {
10512  NK_ASSERT(z->ey >= scan_y_top);
10513  /* insert at front */
10514  z->next = active;
10515  active = z;
10516  }
10517  }
10518  ++e;
10519  }
10520 
10521  /* now process all active edges */
10522  if (active)
10523  nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
10524 
10525  {
10526  float sum = 0;
10527  for (i=0; i < result->w; ++i) {
10528  float k;
10529  int m;
10530  sum += scanline2[i];
10531  k = scanline[i] + sum;
10532  k = (float) NK_ABS(k) * 255.0f + 0.5f;
10533  m = (int) k;
10534  if (m > 255) m = 255;
10535  result->pixels[j*result->stride + i] = (unsigned char) m;
10536  }
10537  }
10538  /* advance all the edges */
10539  step = &active;
10540  while (*step) {
10541  struct nk_tt__active_edge *z = *step;
10542  z->fx += z->fdx; /* advance to position for current scanline */
10543  step = &((*step)->next); /* advance through list */
10544  }
10545  ++y;
10546  ++j;
10547  }
10548  nk_tt__hheap_cleanup(&hh);
10549  if (scanline != scanline_data)
10550  alloc->free(alloc->userdata, scanline);
10551 }
10552 
10553 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0)
10554 NK_INTERN void
10555 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
10556 {
10557  int i,j;
10558  for (i=1; i < n; ++i) {
10559  struct nk_tt__edge t = p[i], *a = &t;
10560  j = i;
10561  while (j > 0) {
10562  struct nk_tt__edge *b = &p[j-1];
10563  int c = NK_TT__COMPARE(a,b);
10564  if (!c) break;
10565  p[j] = p[j-1];
10566  --j;
10567  }
10568  if (i != j)
10569  p[j] = t;
10570  }
10571 }
10572 
10573 NK_INTERN void
10574 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
10575 {
10576  /* threshold for transitioning to insertion sort */
10577  while (n > 12) {
10578  struct nk_tt__edge t;
10579  int c01,c12,c,m,i,j;
10580 
10581  /* compute median of three */
10582  m = n >> 1;
10583  c01 = NK_TT__COMPARE(&p[0],&p[m]);
10584  c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
10585 
10586  /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
10587  if (c01 != c12) {
10588  /* otherwise, we'll need to swap something else to middle */
10589  int z;
10590  c = NK_TT__COMPARE(&p[0],&p[n-1]);
10591  /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
10592  /* 0<mid && mid>n: 0>n => 0; 0<n => n */
10593  z = (c == c12) ? 0 : n-1;
10594  t = p[z];
10595  p[z] = p[m];
10596  p[m] = t;
10597  }
10598 
10599  /* now p[m] is the median-of-three */
10600  /* swap it to the beginning so it won't move around */
10601  t = p[0];
10602  p[0] = p[m];
10603  p[m] = t;
10604 
10605  /* partition loop */
10606  i=1;
10607  j=n-1;
10608  for(;;) {
10609  /* handling of equality is crucial here */
10610  /* for sentinels & efficiency with duplicates */
10611  for (;;++i) {
10612  if (!NK_TT__COMPARE(&p[i], &p[0])) break;
10613  }
10614  for (;;--j) {
10615  if (!NK_TT__COMPARE(&p[0], &p[j])) break;
10616  }
10617 
10618  /* make sure we haven't crossed */
10619  if (i >= j) break;
10620  t = p[i];
10621  p[i] = p[j];
10622  p[j] = t;
10623 
10624  ++i;
10625  --j;
10626 
10627  }
10628 
10629  /* recurse on smaller side, iterate on larger */
10630  if (j < (n-i)) {
10631  nk_tt__sort_edges_quicksort(p,j);
10632  p = p+i;
10633  n = n-i;
10634  } else {
10635  nk_tt__sort_edges_quicksort(p+i, n-i);
10636  n = j;
10637  }
10638  }
10639 }
10640 
10641 NK_INTERN void
10642 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
10643 {
10644  nk_tt__sort_edges_quicksort(p, n);
10645  nk_tt__sort_edges_ins_sort(p, n);
10646 }
10647 
10648 NK_INTERN void
10649 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
10650  int *wcount, int windings, float scale_x, float scale_y,
10651  float shift_x, float shift_y, int off_x, int off_y, int invert,
10652  struct nk_allocator *alloc)
10653 {
10654  float y_scale_inv = invert ? -scale_y : scale_y;
10655  struct nk_tt__edge *e;
10656  int n,i,j,k,m;
10657  int vsubsample = 1;
10658  /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
10659 
10660  /* now we have to blow out the windings into explicit edge lists */
10661  n = 0;
10662  for (i=0; i < windings; ++i)
10663  n += wcount[i];
10664 
10665  e = (struct nk_tt__edge*)
10666  alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
10667  if (e == 0) return;
10668  n = 0;
10669 
10670  m=0;
10671  for (i=0; i < windings; ++i)
10672  {
10673  struct nk_tt__point *p = pts + m;
10674  m += wcount[i];
10675  j = wcount[i]-1;
10676  for (k=0; k < wcount[i]; j=k++) {
10677  int a=k,b=j;
10678  /* skip the edge if horizontal */
10679  if (p[j].y == p[k].y)
10680  continue;
10681 
10682  /* add edge from j to k to the list */
10683  e[n].invert = 0;
10684  if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
10685  e[n].invert = 1;
10686  a=j,b=k;
10687  }
10688  e[n].x0 = p[a].x * scale_x + shift_x;
10689  e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
10690  e[n].x1 = p[b].x * scale_x + shift_x;
10691  e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
10692  ++n;
10693  }
10694  }
10695 
10696  /* now sort the edges by their highest point (should snap to integer, and then by x) */
10697  /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
10698  nk_tt__sort_edges(e, n);
10699  /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
10700  nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
10701  alloc->free(alloc->userdata, e);
10702 }
10703 
10704 NK_INTERN void
10705 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
10706 {
10707  if (!points) return; /* during first pass, it's unallocated */
10708  points[n].x = x;
10709  points[n].y = y;
10710 }
10711 
10712 NK_INTERN int
10713 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
10714  float x0, float y0, float x1, float y1, float x2, float y2,
10715  float objspace_flatness_squared, int n)
10716 {
10717  /* tesselate until threshold p is happy...
10718  * @TODO warped to compensate for non-linear stretching */
10719  /* midpoint */
10720  float mx = (x0 + 2*x1 + x2)/4;
10721  float my = (y0 + 2*y1 + y2)/4;
10722  /* versus directly drawn line */
10723  float dx = (x0+x2)/2 - mx;
10724  float dy = (y0+y2)/2 - my;
10725  if (n > 16) /* 65536 segments on one curve better be enough! */
10726  return 1;
10727 
10728  /* half-pixel error allowed... need to be smaller if AA */
10729  if (dx*dx+dy*dy > objspace_flatness_squared) {
10730  nk_tt__tesselate_curve(points, num_points, x0,y0,
10731  (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
10732  nk_tt__tesselate_curve(points, num_points, mx,my,
10733  (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
10734  } else {
10735  nk_tt__add_point(points, *num_points,x2,y2);
10736  *num_points = *num_points+1;
10737  }
10738  return 1;
10739 }
10740 
10741 /* returns number of contours */
10742 NK_INTERN struct nk_tt__point*
10743 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
10744  float objspace_flatness, int **contour_lengths, int *num_contours,
10745  struct nk_allocator *alloc)
10746 {
10747  struct nk_tt__point *points=0;
10748  int num_points=0;
10749  float objspace_flatness_squared = objspace_flatness * objspace_flatness;
10750  int i;
10751  int n=0;
10752  int start=0;
10753  int pass;
10754 
10755  /* count how many "moves" there are to get the contour count */
10756  for (i=0; i < num_verts; ++i)
10757  if (vertices[i].type == NK_TT_vmove) ++n;
10758 
10759  *num_contours = n;
10760  if (n == 0) return 0;
10761 
10762  *contour_lengths = (int *)
10763  alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
10764  if (*contour_lengths == 0) {
10765  *num_contours = 0;
10766  return 0;
10767  }
10768 
10769  /* make two passes through the points so we don't need to realloc */
10770  for (pass=0; pass < 2; ++pass)
10771  {
10772  float x=0,y=0;
10773  if (pass == 1) {
10774  points = (struct nk_tt__point *)
10775  alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
10776  if (points == 0) goto error;
10777  }
10778  num_points = 0;
10779  n= -1;
10780 
10781  for (i=0; i < num_verts; ++i)
10782  {
10783  switch (vertices[i].type) {
10784  case NK_TT_vmove:
10785  /* start the next contour */
10786  if (n >= 0)
10787  (*contour_lengths)[n] = num_points - start;
10788  ++n;
10789  start = num_points;
10790 
10791  x = vertices[i].x, y = vertices[i].y;
10792  nk_tt__add_point(points, num_points++, x,y);
10793  break;
10794  case NK_TT_vline:
10795  x = vertices[i].x, y = vertices[i].y;
10796  nk_tt__add_point(points, num_points++, x, y);
10797  break;
10798  case NK_TT_vcurve:
10799  nk_tt__tesselate_curve(points, &num_points, x,y,
10800  vertices[i].cx, vertices[i].cy,
10801  vertices[i].x, vertices[i].y,
10802  objspace_flatness_squared, 0);
10803  x = vertices[i].x, y = vertices[i].y;
10804  break;
10805  default: break;
10806  }
10807  }
10808  (*contour_lengths)[n] = num_points - start;
10809  }
10810  return points;
10811 
10812 error:
10813  alloc->free(alloc->userdata, points);
10814  alloc->free(alloc->userdata, *contour_lengths);
10815  *contour_lengths = 0;
10816  *num_contours = 0;
10817  return 0;
10818 }
10819 
10820 NK_INTERN void
10821 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
10822  struct nk_tt_vertex *vertices, int num_verts,
10823  float scale_x, float scale_y, float shift_x, float shift_y,
10824  int x_off, int y_off, int invert, struct nk_allocator *alloc)
10825 {
10826  float scale = scale_x > scale_y ? scale_y : scale_x;
10827  int winding_count, *winding_lengths;
10828  struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
10829  flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
10830 
10831  NK_ASSERT(alloc);
10832  if (windings) {
10833  nk_tt__rasterize(result, windings, winding_lengths, winding_count,
10834  scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
10835  alloc->free(alloc->userdata, winding_lengths);
10836  alloc->free(alloc->userdata, windings);
10837  }
10838 }
10839 
10840 NK_INTERN void
10841 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
10842  int out_w, int out_h, int out_stride, float scale_x, float scale_y,
10843  float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
10844 {
10845  int ix0,iy0;
10846  struct nk_tt_vertex *vertices;
10847  int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
10848  struct nk_tt__bitmap gbm;
10849 
10850  nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
10851  shift_y, &ix0,&iy0,0,0);
10852  gbm.pixels = output;
10853  gbm.w = out_w;
10854  gbm.h = out_h;
10855  gbm.stride = out_stride;
10856 
10857  if (gbm.w && gbm.h)
10858  nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
10859  shift_x, shift_y, ix0,iy0, 1, alloc);
10860  alloc->free(alloc->userdata, vertices);
10861 }
10862 
10863 /*-------------------------------------------------------------
10864  * Bitmap baking
10865  * --------------------------------------------------------------*/
10866 NK_INTERN int
10867 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
10868  int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
10869 {
10870  int num_nodes = pw - padding;
10871  struct nk_rp_context *context = (struct nk_rp_context *)
10872  alloc->alloc(alloc->userdata,0, sizeof(*context));
10873  struct nk_rp_node *nodes = (struct nk_rp_node*)
10874  alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes));
10875 
10876  if (context == 0 || nodes == 0) {
10877  if (context != 0) alloc->free(alloc->userdata, context);
10878  if (nodes != 0) alloc->free(alloc->userdata, nodes);
10879  return 0;
10880  }
10881 
10882  spc->width = pw;
10883  spc->height = ph;
10884  spc->pixels = pixels;
10885  spc->pack_info = context;
10886  spc->nodes = nodes;
10887  spc->padding = padding;
10888  spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
10889  spc->h_oversample = 1;
10890  spc->v_oversample = 1;
10891 
10892  nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
10893  if (pixels)
10894  NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
10895  return 1;
10896 }
10897 
10898 NK_INTERN void
10899 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
10900 {
10901  alloc->free(alloc->userdata, spc->nodes);
10902  alloc->free(alloc->userdata, spc->pack_info);
10903 }
10904 
10905 NK_INTERN void
10906 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
10907  unsigned int h_oversample, unsigned int v_oversample)
10908 {
10909  NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
10910  NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
10911  if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
10912  spc->h_oversample = h_oversample;
10913  if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
10914  spc->v_oversample = v_oversample;
10915 }
10916 
10917 NK_INTERN void
10918 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10919  int kernel_width)
10920 {
10921  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10922  int safe_w = w - kernel_width;
10923  int j;
10924 
10925  for (j=0; j < h; ++j)
10926  {
10927  int i;
10928  unsigned int total;
10929  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10930 
10931  total = 0;
10932 
10933  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10934  switch (kernel_width) {
10935  case 2:
10936  for (i=0; i <= safe_w; ++i) {
10937  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10938  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10939  pixels[i] = (unsigned char) (total / 2);
10940  }
10941  break;
10942  case 3:
10943  for (i=0; i <= safe_w; ++i) {
10944  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10945  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10946  pixels[i] = (unsigned char) (total / 3);
10947  }
10948  break;
10949  case 4:
10950  for (i=0; i <= safe_w; ++i) {
10951  total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
10952  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10953  pixels[i] = (unsigned char) (total / 4);
10954  }
10955  break;
10956  case 5:
10957  for (i=0; i <= safe_w; ++i) {
10958  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10959  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10960  pixels[i] = (unsigned char) (total / 5);
10961  }
10962  break;
10963  default:
10964  for (i=0; i <= safe_w; ++i) {
10965  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10966  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10967  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10968  }
10969  break;
10970  }
10971 
10972  for (; i < w; ++i) {
10973  NK_ASSERT(pixels[i] == 0);
10974  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10975  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10976  }
10977  pixels += stride_in_bytes;
10978  }
10979 }
10980 
10981 NK_INTERN void
10982 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10983  int kernel_width)
10984 {
10985  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10986  int safe_h = h - kernel_width;
10987  int j;
10988 
10989  for (j=0; j < w; ++j)
10990  {
10991  int i;
10992  unsigned int total;
10993  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10994 
10995  total = 0;
10996 
10997  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10998  switch (kernel_width) {
10999  case 2:
11000  for (i=0; i <= safe_h; ++i) {
11001  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11002  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11003  pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
11004  }
11005  break;
11006  case 3:
11007  for (i=0; i <= safe_h; ++i) {
11008  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11009  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11010  pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
11011  }
11012  break;
11013  case 4:
11014  for (i=0; i <= safe_h; ++i) {
11015  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11016  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11017  pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
11018  }
11019  break;
11020  case 5:
11021  for (i=0; i <= safe_h; ++i) {
11022  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11023  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11024  pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
11025  }
11026  break;
11027  default:
11028  for (i=0; i <= safe_h; ++i) {
11029  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11030  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11031  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
11032  }
11033  break;
11034  }
11035 
11036  for (; i < h; ++i) {
11037  NK_ASSERT(pixels[i*stride_in_bytes] == 0);
11038  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
11039  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
11040  }
11041  pixels += 1;
11042  }
11043 }
11044 
11045 NK_INTERN float
11046 nk_tt__oversample_shift(int oversample)
11047 {
11048  if (!oversample)
11049  return 0.0f;
11050 
11051  /* The prefilter is a box filter of width "oversample", */
11052  /* which shifts phase by (oversample - 1)/2 pixels in */
11053  /* oversampled space. We want to shift in the opposite */
11054  /* direction to counter this. */
11055  return (float)-(oversample - 1) / (2.0f * (float)oversample);
11056 }
11057 
11058 /* rects array must be big enough to accommodate all characters in the given ranges */
11059 NK_INTERN int
11060 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
11061  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
11062  int num_ranges, struct nk_rp_rect *rects)
11063 {
11064  int i,j,k;
11065  k = 0;
11066 
11067  for (i=0; i < num_ranges; ++i) {
11068  float fh = ranges[i].font_size;
11069  float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
11070  nk_tt_ScaleForMappingEmToPixels(info, -fh);
11071  ranges[i].h_oversample = (unsigned char) spc->h_oversample;
11072  ranges[i].v_oversample = (unsigned char) spc->v_oversample;
11073  for (j=0; j < ranges[i].num_chars; ++j) {
11074  int x0,y0,x1,y1;
11075  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
11076  ranges[i].first_unicode_codepoint_in_range + j :
11077  ranges[i].array_of_unicode_codepoints[j];
11078 
11079  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
11080  nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
11081  scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
11082  rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
11083  rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
11084  ++k;
11085  }
11086  }
11087  return k;
11088 }
11089 
11090 NK_INTERN int
11091 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
11092  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
11093  int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
11094 {
11095  int i,j,k, return_value = 1;
11096  /* save current values */
11097  int old_h_over = (int)spc->h_oversample;
11098  int old_v_over = (int)spc->v_oversample;
11099  /* rects array must be big enough to accommodate all characters in the given ranges */
11100 
11101  k = 0;
11102  for (i=0; i < num_ranges; ++i)
11103  {
11104  float fh = ranges[i].font_size;
11105  float recip_h,recip_v,sub_x,sub_y;
11106  float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
11107  nk_tt_ScaleForMappingEmToPixels(info, -fh);
11108 
11109  spc->h_oversample = ranges[i].h_oversample;
11110  spc->v_oversample = ranges[i].v_oversample;
11111 
11112  recip_h = 1.0f / (float)spc->h_oversample;
11113  recip_v = 1.0f / (float)spc->v_oversample;
11114 
11115  sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
11116  sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
11117 
11118  for (j=0; j < ranges[i].num_chars; ++j)
11119  {
11120  struct nk_rp_rect *r = &rects[k];
11121  if (r->was_packed)
11122  {
11123  struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
11124  int advance, lsb, x0,y0,x1,y1;
11125  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
11126  ranges[i].first_unicode_codepoint_in_range + j :
11127  ranges[i].array_of_unicode_codepoints[j];
11128  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
11129  nk_rp_coord pad = (nk_rp_coord) spc->padding;
11130 
11131  /* pad on left and top */
11132  r->x = (nk_rp_coord)((int)r->x + (int)pad);
11133  r->y = (nk_rp_coord)((int)r->y + (int)pad);
11134  r->w = (nk_rp_coord)((int)r->w - (int)pad);
11135  r->h = (nk_rp_coord)((int)r->h - (int)pad);
11136 
11137  nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
11138  nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
11139  (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
11140  nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
11141  (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
11142  spc->stride_in_bytes, scale * (float)spc->h_oversample,
11143  scale * (float)spc->v_oversample, 0,0, glyph, alloc);
11144 
11145  if (spc->h_oversample > 1)
11146  nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
11147  r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
11148 
11149  if (spc->v_oversample > 1)
11150  nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
11151  r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
11152 
11153  bc->x0 = (nk_ushort) r->x;
11154  bc->y0 = (nk_ushort) r->y;
11155  bc->x1 = (nk_ushort) (r->x + r->w);
11156  bc->y1 = (nk_ushort) (r->y + r->h);
11157  bc->xadvance = scale * (float)advance;
11158  bc->xoff = (float) x0 * recip_h + sub_x;
11159  bc->yoff = (float) y0 * recip_v + sub_y;
11160  bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x;
11161  bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y;
11162  } else {
11163  return_value = 0; /* if any fail, report failure */
11164  }
11165  ++k;
11166  }
11167  }
11168  /* restore original values */
11169  spc->h_oversample = (unsigned int)old_h_over;
11170  spc->v_oversample = (unsigned int)old_v_over;
11171  return return_value;
11172 }
11173 
11174 NK_INTERN void
11175 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
11176  int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
11177  int align_to_integer)
11178 {
11179  float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
11180  struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
11181  if (align_to_integer) {
11182  int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
11183  int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
11184 
11185  float x = (float)tx;
11186  float y = (float)ty;
11187 
11188  q->x0 = x;
11189  q->y0 = y;
11190  q->x1 = x + b->xoff2 - b->xoff;
11191  q->y1 = y + b->yoff2 - b->yoff;
11192  } else {
11193  q->x0 = *xpos + b->xoff;
11194  q->y0 = *ypos + b->yoff;
11195  q->x1 = *xpos + b->xoff2;
11196  q->y1 = *ypos + b->yoff2;
11197  }
11198  q->s0 = b->x0 * ipw;
11199  q->t0 = b->y0 * iph;
11200  q->s1 = b->x1 * ipw;
11201  q->t1 = b->y1 * iph;
11202  *xpos += b->xadvance;
11203 }
11204 
11205 /* -------------------------------------------------------------
11206  *
11207  * FONT BAKING
11208  *
11209  * --------------------------------------------------------------*/
11210 struct nk_font_bake_data {
11211  struct nk_tt_fontinfo info;
11212  struct nk_rp_rect *rects;
11213  struct nk_tt_pack_range *ranges;
11214  nk_rune range_count;
11215 };
11216 
11217 struct nk_font_baker {
11218  struct nk_allocator alloc;
11219  struct nk_tt_pack_context spc;
11220  struct nk_font_bake_data *build;
11221  struct nk_tt_packedchar *packed_chars;
11222  struct nk_rp_rect *rects;
11223  struct nk_tt_pack_range *ranges;
11224 };
11225 
11226 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
11227 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
11228 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
11229 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
11230 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
11231 
11232 NK_INTERN int
11233 nk_range_count(const nk_rune *range)
11234 {
11235  const nk_rune *iter = range;
11236  NK_ASSERT(range);
11237  if (!range) return 0;
11238  while (*(iter++) != 0);
11239  return (iter == range) ? 0 : (int)((iter - range)/2);
11240 }
11241 
11242 NK_INTERN int
11243 nk_range_glyph_count(const nk_rune *range, int count)
11244 {
11245  int i = 0;
11246  int total_glyphs = 0;
11247  for (i = 0; i < count; ++i) {
11248  int diff;
11249  nk_rune f = range[(i*2)+0];
11250  nk_rune t = range[(i*2)+1];
11251  NK_ASSERT(t >= f);
11252  diff = (int)((t - f) + 1);
11253  total_glyphs += diff;
11254  }
11255  return total_glyphs;
11256 }
11257 
11258 NK_API const nk_rune*
11259 nk_font_default_glyph_ranges(void)
11260 {
11261  NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
11262  return ranges;
11263 }
11264 
11265 NK_API const nk_rune*
11266 nk_font_chinese_glyph_ranges(void)
11267 {
11268  NK_STORAGE const nk_rune ranges[] = {
11269  0x0020, 0x00FF,
11270  0x3000, 0x30FF,
11271  0x31F0, 0x31FF,
11272  0xFF00, 0xFFEF,
11273  0x4e00, 0x9FAF,
11274  0
11275  };
11276  return ranges;
11277 }
11278 
11279 NK_API const nk_rune*
11280 nk_font_cyrillic_glyph_ranges(void)
11281 {
11282  NK_STORAGE const nk_rune ranges[] = {
11283  0x0020, 0x00FF,
11284  0x0400, 0x052F,
11285  0x2DE0, 0x2DFF,
11286  0xA640, 0xA69F,
11287  0
11288  };
11289  return ranges;
11290 }
11291 
11292 NK_API const nk_rune*
11293 nk_font_korean_glyph_ranges(void)
11294 {
11295  NK_STORAGE const nk_rune ranges[] = {
11296  0x0020, 0x00FF,
11297  0x3131, 0x3163,
11298  0xAC00, 0xD79D,
11299  0
11300  };
11301  return ranges;
11302 }
11303 
11304 NK_INTERN void
11305 nk_font_baker_memory(nk_size *temp, int *glyph_count,
11306  struct nk_font_config *config_list, int count)
11307 {
11308  int range_count = 0;
11309  int total_range_count = 0;
11310  struct nk_font_config *iter;
11311 
11312  NK_ASSERT(config_list);
11313  NK_ASSERT(glyph_count);
11314  if (!config_list) {
11315  *temp = 0;
11316  *glyph_count = 0;
11317  return;
11318  }
11319 
11320  *glyph_count = 0;
11321  if (!config_list->range)
11322  config_list->range = nk_font_default_glyph_ranges();
11323  for (iter = config_list; iter; iter = iter->next) {
11324  range_count = nk_range_count(iter->range);
11325  total_range_count += range_count;
11326  *glyph_count += nk_range_glyph_count(iter->range, range_count);
11327  }
11328 
11329  *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
11330  *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
11331  *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
11332  *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
11333  *temp += sizeof(struct nk_font_baker);
11334  *temp += nk_rect_align + nk_range_align + nk_char_align;
11335  *temp += nk_build_align + nk_baker_align;
11336 }
11337 
11338 NK_INTERN struct nk_font_baker*
11339 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
11340 {
11341  struct nk_font_baker *baker;
11342  if (!memory) return 0;
11343  /* setup baker inside a memory block */
11344  baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
11345  baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
11346  baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
11347  baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
11348  baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
11349  baker->alloc = *alloc;
11350  return baker;
11351 }
11352 
11353 NK_INTERN int
11354 nk_font_bake_pack(struct nk_font_baker *baker,
11355  nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
11356  const struct nk_font_config *config_list, int count,
11357  struct nk_allocator *alloc)
11358 {
11359  NK_STORAGE const nk_size max_height = 1024 * 32;
11360  const struct nk_font_config *config_iter;
11361  int total_glyph_count = 0;
11362  int total_range_count = 0;
11363  int range_count = 0;
11364  int i = 0;
11365 
11366  NK_ASSERT(image_memory);
11367  NK_ASSERT(width);
11368  NK_ASSERT(height);
11369  NK_ASSERT(config_list);
11370  NK_ASSERT(count);
11371  NK_ASSERT(alloc);
11372 
11373  if (!image_memory || !width || !height || !config_list || !count) return nk_false;
11374  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11375  range_count = nk_range_count(config_iter->range);
11376  total_range_count += range_count;
11377  total_glyph_count += nk_range_glyph_count(config_iter->range, range_count);
11378  }
11379 
11380  /* setup font baker from temporary memory */
11381  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11382  const struct nk_font_config *cfg = config_iter;
11383  if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)cfg->ttf_blob, 0))
11384  return nk_false;
11385  }
11386 
11387  *height = 0;
11388  *width = (total_glyph_count > 1000) ? 1024 : 512;
11389  nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
11390  {
11391  int input_i = 0;
11392  int range_n = 0;
11393  int rect_n = 0;
11394  int char_n = 0;
11395 
11396  if (custom) {
11397  /* pack custom user data first so it will be in the upper left corner*/
11398  struct nk_rp_rect custom_space;
11399  nk_zero(&custom_space, sizeof(custom_space));
11400  custom_space.w = (nk_rp_coord)((custom->w * 2) + 1);
11401  custom_space.h = (nk_rp_coord)(custom->h + 1);
11402 
11403  nk_tt_PackSetOversampling(&baker->spc, 1, 1);
11404  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
11405  *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
11406 
11407  custom->x = (short)custom_space.x;
11408  custom->y = (short)custom_space.y;
11409  custom->w = (short)custom_space.w;
11410  custom->h = (short)custom_space.h;
11411  }
11412 
11413  /* first font pass: pack all glyphs */
11414  for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
11415  input_i++, config_iter = config_iter->next)
11416  {
11417  int n = 0;
11418  int glyph_count;
11419  const nk_rune *in_range;
11420  const struct nk_font_config *cfg = config_iter;
11421  struct nk_font_bake_data *tmp = &baker->build[input_i];
11422 
11423  /* count glyphs + ranges in current font */
11424  glyph_count = 0; range_count = 0;
11425  for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
11426  glyph_count += (int)(in_range[1] - in_range[0]) + 1;
11427  range_count++;
11428  }
11429 
11430  /* setup ranges */
11431  tmp->ranges = baker->ranges + range_n;
11432  tmp->range_count = (nk_rune)range_count;
11433  range_n += range_count;
11434  for (i = 0; i < range_count; ++i) {
11435  in_range = &cfg->range[i * 2];
11436  tmp->ranges[i].font_size = cfg->size;
11437  tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
11438  tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
11439  tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
11440  char_n += tmp->ranges[i].num_chars;
11441  }
11442 
11443  /* pack */
11444  tmp->rects = baker->rects + rect_n;
11445  rect_n += glyph_count;
11446  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11447  n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
11448  tmp->ranges, (int)tmp->range_count, tmp->rects);
11449  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
11450 
11451  /* texture height */
11452  for (i = 0; i < n; ++i) {
11453  if (tmp->rects[i].was_packed)
11454  *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
11455  }
11456  }
11457  NK_ASSERT(rect_n == total_glyph_count);
11458  NK_ASSERT(char_n == total_glyph_count);
11459  NK_ASSERT(range_n == total_range_count);
11460  }
11461  *height = (int)nk_round_up_pow2((nk_uint)*height);
11462  *image_memory = (nk_size)(*width) * (nk_size)(*height);
11463  return nk_true;
11464 }
11465 
11466 NK_INTERN void
11467 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
11468  struct nk_font_glyph *glyphs, int glyphs_count,
11469  const struct nk_font_config *config_list, int font_count)
11470 {
11471  int input_i = 0;
11472  nk_rune glyph_n = 0;
11473  const struct nk_font_config *config_iter;
11474 
11475  NK_ASSERT(image_memory);
11476  NK_ASSERT(width);
11477  NK_ASSERT(height);
11478  NK_ASSERT(config_list);
11479  NK_ASSERT(baker);
11480  NK_ASSERT(font_count);
11481  NK_ASSERT(glyphs_count);
11482  if (!image_memory || !width || !height || !config_list ||
11483  !font_count || !glyphs || !glyphs_count)
11484  return;
11485 
11486  /* second font pass: render glyphs */
11487  nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
11488  baker->spc.pixels = (unsigned char*)image_memory;
11489  baker->spc.height = (int)height;
11490  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11491  ++input_i, config_iter = config_iter->next)
11492  {
11493  const struct nk_font_config *cfg = config_iter;
11494  struct nk_font_bake_data *tmp = &baker->build[input_i];
11495  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11496  nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
11497  (int)tmp->range_count, tmp->rects, &baker->alloc);
11498  }
11499  nk_tt_PackEnd(&baker->spc, &baker->alloc);
11500 
11501  /* third pass: setup font and glyphs */
11502  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11503  ++input_i, config_iter = config_iter->next)
11504  {
11505  nk_size i = 0;
11506  int char_idx = 0;
11507  nk_rune glyph_count = 0;
11508  const struct nk_font_config *cfg = config_iter;
11509  struct nk_font_bake_data *tmp = &baker->build[input_i];
11510  struct nk_baked_font *dst_font = cfg->font;
11511 
11512  float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
11513  int unscaled_ascent, unscaled_descent, unscaled_line_gap;
11514  nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
11515  &unscaled_line_gap);
11516 
11517  /* fill baked font */
11518  if (!cfg->merge_mode) {
11519  dst_font->ranges = cfg->range;
11520  dst_font->height = cfg->size;
11521  dst_font->ascent = ((float)unscaled_ascent * font_scale);
11522  dst_font->descent = ((float)unscaled_descent * font_scale);
11523  dst_font->glyph_offset = glyph_n;
11524  }
11525 
11526  /* fill own baked font glyph array */
11527  for (i = 0; i < tmp->range_count; ++i)
11528  {
11529  struct nk_tt_pack_range *range = &tmp->ranges[i];
11530  for (char_idx = 0; char_idx < range->num_chars; char_idx++)
11531  {
11532  nk_rune codepoint = 0;
11533  float dummy_x = 0, dummy_y = 0;
11534  struct nk_tt_aligned_quad q;
11535  struct nk_font_glyph *glyph;
11536 
11537  /* query glyph bounds from stb_truetype */
11538  const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
11539  if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
11540  codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
11541  nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
11542  (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
11543 
11544  /* fill own glyph type with data */
11545  glyph = &glyphs[dst_font->glyph_offset + (unsigned int)glyph_count];
11546  glyph->codepoint = codepoint;
11547  glyph->x0 = q.x0; glyph->y0 = q.y0;
11548  glyph->x1 = q.x1; glyph->y1 = q.y1;
11549  glyph->y0 += (dst_font->ascent + 0.5f);
11550  glyph->y1 += (dst_font->ascent + 0.5f);
11551  glyph->w = glyph->x1 - glyph->x0 + 0.5f;
11552  glyph->h = glyph->y1 - glyph->y0;
11553 
11554  if (cfg->coord_type == NK_COORD_PIXEL) {
11555  glyph->u0 = q.s0 * (float)width;
11556  glyph->v0 = q.t0 * (float)height;
11557  glyph->u1 = q.s1 * (float)width;
11558  glyph->v1 = q.t1 * (float)height;
11559  } else {
11560  glyph->u0 = q.s0;
11561  glyph->v0 = q.t0;
11562  glyph->u1 = q.s1;
11563  glyph->v1 = q.t1;
11564  }
11565  glyph->xadvance = (pc->xadvance + cfg->spacing.x);
11566  if (cfg->pixel_snap)
11567  glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
11568  glyph_count++;
11569  }
11570  }
11571  dst_font->glyph_count = glyph_count;
11572  glyph_n += dst_font->glyph_count;
11573  }
11574 }
11575 
11576 NK_INTERN void
11577 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
11578  struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
11579  int tex_height, char white, char black)
11580 {
11581  nk_byte *pixels;
11582  int y = 0;
11583  int x = 0;
11584  int n = 0;
11585 
11586  NK_ASSERT(img_memory);
11587  NK_ASSERT(img_width);
11588  NK_ASSERT(img_height);
11589  NK_ASSERT(texture_data_mask);
11590  NK_UNUSED(tex_height);
11591  if (!img_memory || !img_width || !img_height || !texture_data_mask)
11592  return;
11593 
11594  pixels = (nk_byte*)img_memory;
11595  for (y = 0, n = 0; y < tex_height; ++y) {
11596  for (x = 0; x < tex_width; ++x, ++n) {
11597  const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
11598  const int off1 = off0 + 1 + tex_width;
11599  pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
11600  pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
11601  }
11602  }
11603 }
11604 
11605 NK_INTERN void
11606 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
11607  const void *in_memory)
11608 {
11609  int n = 0;
11610  nk_rune *dst;
11611  const nk_byte *src;
11612 
11613  NK_ASSERT(out_memory);
11614  NK_ASSERT(in_memory);
11615  NK_ASSERT(img_width);
11616  NK_ASSERT(img_height);
11617  if (!out_memory || !in_memory || !img_height || !img_width) return;
11618 
11619  dst = (nk_rune*)out_memory;
11620  src = (const nk_byte*)in_memory;
11621  for (n = (int)(img_width * img_height); n > 0; n--)
11622  *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
11623 }
11624 
11625 /* -------------------------------------------------------------
11626  *
11627  * FONT
11628  *
11629  * --------------------------------------------------------------*/
11630 NK_INTERN float
11631 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
11632 {
11633  nk_rune unicode;
11634  int text_len = 0;
11635  float text_width = 0;
11636  int glyph_len = 0;
11637  float scale = 0;
11638 
11639  struct nk_font *font = (struct nk_font*)handle.ptr;
11640  NK_ASSERT(font);
11641  NK_ASSERT(font->glyphs);
11642  if (!font || !text || !len)
11643  return 0;
11644 
11645  scale = height/font->info.height;
11646  glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
11647  if (!glyph_len) return 0;
11648  while (text_len <= (int)len && glyph_len) {
11649  const struct nk_font_glyph *g;
11650  if (unicode == NK_UTF_INVALID) break;
11651 
11652  /* query currently drawn glyph information */
11653  g = nk_font_find_glyph(font, unicode);
11654  text_width += g->xadvance * scale;
11655 
11656  /* offset next glyph */
11657  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
11658  text_len += glyph_len;
11659  }
11660  return text_width;
11661 }
11662 
11663 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11664 NK_INTERN void
11665 nk_font_query_font_glyph(nk_handle handle, float height,
11666  struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
11667 {
11668  float scale;
11669  const struct nk_font_glyph *g;
11670  struct nk_font *font;
11671 
11672  NK_ASSERT(glyph);
11673  NK_UNUSED(next_codepoint);
11674 
11675  font = (struct nk_font*)handle.ptr;
11676  NK_ASSERT(font);
11677  NK_ASSERT(font->glyphs);
11678  if (!font || !glyph)
11679  return;
11680 
11681  scale = height/font->info.height;
11682  g = nk_font_find_glyph(font, codepoint);
11683  glyph->width = (g->x1 - g->x0) * scale;
11684  glyph->height = (g->y1 - g->y0) * scale;
11685  glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
11686  glyph->xadvance = (g->xadvance * scale);
11687  glyph->uv[0] = nk_vec2(g->u0, g->v0);
11688  glyph->uv[1] = nk_vec2(g->u1, g->v1);
11689 }
11690 #endif
11691 
11692 NK_API const struct nk_font_glyph*
11693 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
11694 {
11695  int i = 0;
11696  int count;
11697  int total_glyphs = 0;
11698  const struct nk_font_glyph *glyph = 0;
11699 
11700  NK_ASSERT(font);
11701  NK_ASSERT(font->glyphs);
11702  NK_ASSERT(font->info.ranges);
11703  if (!font || !font->glyphs) return 0;
11704 
11705  glyph = font->fallback;
11706  count = nk_range_count(font->info.ranges);
11707  for (i = 0; i < count; ++i) {
11708  nk_rune f = font->info.ranges[(i*2)+0];
11709  nk_rune t = font->info.ranges[(i*2)+1];
11710  int diff = (int)((t - f) + 1);
11711  if (unicode >= f && unicode <= t)
11712  return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
11713  total_glyphs += diff;
11714  }
11715  return glyph;
11716 }
11717 
11718 NK_INTERN void
11719 nk_font_init(struct nk_font *font, float pixel_height,
11720  nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
11721  const struct nk_baked_font *baked_font, nk_handle atlas)
11722 {
11723  struct nk_baked_font baked;
11724  NK_ASSERT(font);
11725  NK_ASSERT(glyphs);
11726  NK_ASSERT(baked_font);
11727  if (!font || !glyphs || !baked_font)
11728  return;
11729 
11730  baked = *baked_font;
11731  font->fallback = 0;
11732  font->info = baked;
11733  font->scale = (float)pixel_height / (float)font->info.height;
11734  font->glyphs = &glyphs[baked_font->glyph_offset];
11735  font->texture = atlas;
11736  font->fallback_codepoint = fallback_codepoint;
11737  font->fallback = nk_font_find_glyph(font, fallback_codepoint);
11738 
11739  font->handle.height = font->info.height * font->scale;
11740  font->handle.width = nk_font_text_width;
11741  font->handle.userdata.ptr = font;
11742 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11743  font->handle.query = nk_font_query_font_glyph;
11744  font->handle.texture = font->texture;
11745 #endif
11746 }
11747 
11748 /* ---------------------------------------------------------------------------
11749  *
11750  * DEFAULT FONT
11751  *
11752  * ProggyClean.ttf
11753  * Copyright (c) 2004, 2005 Tristan Grimmer
11754  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
11755  * Download and more information at http://upperbounds.net
11756  *-----------------------------------------------------------------------------*/
11757 #ifdef NK_INCLUDE_DEFAULT_FONT
11758 
11759  #ifdef __clang__
11760 #pragma clang diagnostic push
11761 
11762 #pragma clang diagnostic ignored "-Woverlength-strings"
11763 #elif defined(__GNUC__) || defined(__GNUG__)
11764 #pragma GCC diagnostic push
11765 #pragma GCC diagnostic ignored "-Woverlength-strings"
11766 #endif
11767 
11768 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
11769  "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
11770  "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
11771  "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
11772  "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
11773  "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
11774  "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
11775  "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
11776  "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
11777  "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
11778  "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
11779  "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
11780  "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
11781  "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
11782  "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
11783  "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
11784  "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
11785  "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
11786  "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
11787  "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
11788  "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
11789  "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
11790  "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
11791  "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
11792  "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
11793  "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
11794  "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
11795  "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
11796  "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
11797  "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
11798  "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
11799  ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
11800  "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
11801  "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
11802  "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
11803  "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
11804  "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
11805  "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
11806  ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
11807  "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
11808  "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
11809  "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
11810  "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
11811  "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
11812  "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
11813  "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
11814  "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
11815  ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
11816  "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
11817  "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
11818  ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
11819  "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
11820  "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
11821  "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
11822  ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
11823  "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
11824  "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
11825  "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
11826  "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
11827  "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
11828  "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
11829  "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
11830  "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
11831  "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
11832  "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
11833  "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
11834  "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
11835  "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
11836  "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
11837  ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
11838  "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
11839  "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
11840  "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
11841  "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
11842  "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
11843  "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
11844  "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
11845  "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
11846  ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
11847  "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
11848  "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
11849  "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
11850  "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
11851  "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
11852  "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
11853  "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
11854  "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
11855 #endif /* NK_INCLUDE_DEFAULT_FONT */
11856 
11857 #define NK_CURSOR_DATA_W 90
11858 #define NK_CURSOR_DATA_H 27
11859 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
11860 {
11861  "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
11862  "..- -X.....X- X.X - X.X -X.....X - X.....X"
11863  "--- -XXX.XXX- X...X - X...X -X....X - X....X"
11864  "X - X.X - X.....X - X.....X -X...X - X...X"
11865  "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
11866  "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
11867  "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
11868  "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
11869  "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
11870  "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
11871  "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
11872  "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
11873  "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
11874  "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
11875  "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
11876  "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
11877  "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
11878  "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
11879  "X.X X..X - -X.......X- X.......X - XX XX - "
11880  "XX X..X - - X.....X - X.....X - X.X X.X - "
11881  " X..X - X...X - X...X - X..X X..X - "
11882  " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
11883  "------------ - X - X -X.....................X- "
11884  " ----------------------------------- X...XXXXXXXXXXXXX...X - "
11885  " - X..X X..X - "
11886  " - X.X X.X - "
11887  " - XX XX - "
11888 };
11889 
11890 #ifdef __clang__
11891 #pragma clang diagnostic pop
11892 #elif defined(__GNUC__) || defined(__GNUG__)
11893 #pragma GCC diagnostic pop
11894 #endif
11895 
11896 NK_INTERN unsigned int
11897 nk_decompress_length(unsigned char *input)
11898 {
11899  return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
11900 }
11901 
11902 NK_GLOBAL unsigned char *nk__barrier;
11903 NK_GLOBAL unsigned char *nk__barrier2;
11904 NK_GLOBAL unsigned char *nk__barrier3;
11905 NK_GLOBAL unsigned char *nk__barrier4;
11906 NK_GLOBAL unsigned char *nk__dout;
11907 
11908 NK_INTERN void
11909 nk__match(unsigned char *data, unsigned int length)
11910 {
11911  /* INVERSE of memmove... write each byte before copying the next...*/
11912  NK_ASSERT (nk__dout + length <= nk__barrier);
11913  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11914  if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
11915  while (length--) *nk__dout++ = *data++;
11916 }
11917 
11918 NK_INTERN void
11919 nk__lit(unsigned char *data, unsigned int length)
11920 {
11921  NK_ASSERT (nk__dout + length <= nk__barrier);
11922  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11923  if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
11924  NK_MEMCPY(nk__dout, data, length);
11925  nk__dout += length;
11926 }
11927 
11928 #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
11929 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
11930 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
11931 
11932 NK_INTERN unsigned char*
11933 nk_decompress_token(unsigned char *i)
11934 {
11935  if (*i >= 0x20) { /* use fewer if's for cases that expand small */
11936  if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
11937  else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
11938  else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
11939  } else { /* more ifs for cases that expand large, since overhead is amortized */
11940  if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
11941  else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
11942  else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
11943  else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
11944  else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
11945  else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
11946  }
11947  return i;
11948 }
11949 
11950 NK_INTERN unsigned int
11951 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
11952 {
11953  const unsigned long ADLER_MOD = 65521;
11954  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
11955  unsigned long blocklen, i;
11956 
11957  blocklen = buflen % 5552;
11958  while (buflen) {
11959  for (i=0; i + 7 < blocklen; i += 8) {
11960  s1 += buffer[0]; s2 += s1;
11961  s1 += buffer[1]; s2 += s1;
11962  s1 += buffer[2]; s2 += s1;
11963  s1 += buffer[3]; s2 += s1;
11964  s1 += buffer[4]; s2 += s1;
11965  s1 += buffer[5]; s2 += s1;
11966  s1 += buffer[6]; s2 += s1;
11967  s1 += buffer[7]; s2 += s1;
11968  buffer += 8;
11969  }
11970  for (; i < blocklen; ++i) {
11971  s1 += *buffer++; s2 += s1;
11972  }
11973 
11974  s1 %= ADLER_MOD; s2 %= ADLER_MOD;
11975  buflen -= (unsigned int)blocklen;
11976  blocklen = 5552;
11977  }
11978  return (unsigned int)(s2 << 16) + (unsigned int)s1;
11979 }
11980 
11981 NK_INTERN unsigned int
11982 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
11983 {
11984  unsigned int olen;
11985  if (nk__in4(0) != 0x57bC0000) return 0;
11986  if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
11987  olen = nk_decompress_length(i);
11988  nk__barrier2 = i;
11989  nk__barrier3 = i+length;
11990  nk__barrier = output + olen;
11991  nk__barrier4 = output;
11992  i += 16;
11993 
11994  nk__dout = output;
11995  for (;;) {
11996  unsigned char *old_i = i;
11997  i = nk_decompress_token(i);
11998  if (i == old_i) {
11999  if (*i == 0x05 && i[1] == 0xfa) {
12000  NK_ASSERT(nk__dout == output + olen);
12001  if (nk__dout != output + olen) return 0;
12002  if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
12003  return 0;
12004  return olen;
12005  } else {
12006  NK_ASSERT(0); /* NOTREACHED */
12007  return 0;
12008  }
12009  }
12010  NK_ASSERT(nk__dout <= output + olen);
12011  if (nk__dout > output + olen)
12012  return 0;
12013  }
12014 }
12015 
12016 NK_INTERN unsigned int
12017 nk_decode_85_byte(char c)
12018 { return (unsigned int)((c >= '\\') ? c-36 : c-35); }
12019 
12020 NK_INTERN void
12021 nk_decode_85(unsigned char* dst, const unsigned char* src)
12022 {
12023  while (*src)
12024  {
12025  unsigned int tmp =
12026  nk_decode_85_byte((char)src[0]) +
12027  85 * (nk_decode_85_byte((char)src[1]) +
12028  85 * (nk_decode_85_byte((char)src[2]) +
12029  85 * (nk_decode_85_byte((char)src[3]) +
12030  85 * nk_decode_85_byte((char)src[4]))));
12031 
12032  /* we can't assume little-endianess. */
12033  dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
12034  dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
12035  dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
12036  dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
12037 
12038  src += 5;
12039  dst += 4;
12040  }
12041 }
12042 
12043 /* -------------------------------------------------------------
12044  *
12045  * FONT ATLAS
12046  *
12047  * --------------------------------------------------------------*/
12048 NK_API struct nk_font_config
12049 nk_font_config(float pixel_height)
12050 {
12051  struct nk_font_config cfg;
12052  nk_zero_struct(cfg);
12053  cfg.ttf_blob = 0;
12054  cfg.ttf_size = 0;
12055  cfg.ttf_data_owned_by_atlas = 0;
12056  cfg.size = pixel_height;
12057  cfg.oversample_h = 3;
12058  cfg.oversample_v = 1;
12059  cfg.pixel_snap = 0;
12060  cfg.coord_type = NK_COORD_UV;
12061  cfg.spacing = nk_vec2(0,0);
12062  cfg.range = nk_font_default_glyph_ranges();
12063  cfg.merge_mode = 0;
12064  cfg.fallback_glyph = '?';
12065  cfg.font = 0;
12066  return cfg;
12067 }
12068 
12069 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
12070 NK_API void
12071 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
12072 {
12073  NK_ASSERT(atlas);
12074  if (!atlas) return;
12075  nk_zero_struct(*atlas);
12076  atlas->temporary.userdata.ptr = 0;
12077  atlas->temporary.alloc = nk_malloc;
12078  atlas->temporary.free = nk_mfree;
12079  atlas->permanent.userdata.ptr = 0;
12080  atlas->permanent.alloc = nk_malloc;
12081  atlas->permanent.free = nk_mfree;
12082 }
12083 #endif
12084 
12085 NK_API void
12086 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
12087 {
12088  NK_ASSERT(atlas);
12089  NK_ASSERT(alloc);
12090  if (!atlas || !alloc) return;
12091  nk_zero_struct(*atlas);
12092  atlas->permanent = *alloc;
12093  atlas->temporary = *alloc;
12094 }
12095 
12096 NK_API void
12097 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
12098  struct nk_allocator *permanent, struct nk_allocator *temporary)
12099 {
12100  NK_ASSERT(atlas);
12101  NK_ASSERT(permanent);
12102  NK_ASSERT(temporary);
12103  if (!atlas || !permanent || !temporary) return;
12104  nk_zero_struct(*atlas);
12105  atlas->permanent = *permanent;
12106  atlas->temporary = *temporary;
12107 }
12108 
12109 NK_API void
12110 nk_font_atlas_begin(struct nk_font_atlas *atlas)
12111 {
12112  NK_ASSERT(atlas);
12113  NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
12114  NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
12115  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
12116  !atlas->temporary.alloc || !atlas->temporary.free) return;
12117  if (atlas->glyphs) {
12118  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12119  atlas->glyphs = 0;
12120  }
12121  if (atlas->pixel) {
12122  atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
12123  atlas->pixel = 0;
12124  }
12125 }
12126 
12127 NK_API struct nk_font*
12128 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
12129 {
12130  struct nk_font *font = 0;
12131  struct nk_font_config *cfg;
12132 
12133  NK_ASSERT(atlas);
12134  NK_ASSERT(atlas->permanent.alloc);
12135  NK_ASSERT(atlas->permanent.free);
12136  NK_ASSERT(atlas->temporary.alloc);
12137  NK_ASSERT(atlas->temporary.free);
12138 
12139  NK_ASSERT(config);
12140  NK_ASSERT(config->ttf_blob);
12141  NK_ASSERT(config->ttf_size);
12142  NK_ASSERT(config->size > 0.0f);
12143 
12144  if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
12145  !atlas->permanent.alloc || !atlas->permanent.free ||
12146  !atlas->temporary.alloc || !atlas->temporary.free)
12147  return 0;
12148 
12149  /* allocate and insert font config into list */
12150  cfg = (struct nk_font_config*)
12151  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
12152  NK_MEMCPY(cfg, config, sizeof(*config));
12153  if (!atlas->config) {
12154  atlas->config = cfg;
12155  cfg->next = 0;
12156  } else {
12157  cfg->next = atlas->config;
12158  atlas->config = cfg;
12159  }
12160 
12161  /* allocate new font */
12162  if (!config->merge_mode) {
12163  font = (struct nk_font*)
12164  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
12165  NK_ASSERT(font);
12166  if (!font) return 0;
12167  font->config = cfg;
12168  } else {
12169  NK_ASSERT(atlas->font_num);
12170  font = atlas->fonts;
12171  font->config = cfg;
12172  }
12173 
12174  /* insert font into list */
12175  if (!config->merge_mode) {
12176  if (!atlas->fonts) {
12177  atlas->fonts = font;
12178  font->next = 0;
12179  } else {
12180  font->next = atlas->fonts;
12181  atlas->fonts = font;
12182  }
12183  cfg->font = &font->info;
12184  }
12185 
12186  /* create own copy of .TTF font blob */
12187  if (!config->ttf_data_owned_by_atlas) {
12188  cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
12189  NK_ASSERT(cfg->ttf_blob);
12190  if (!cfg->ttf_blob) {
12191  atlas->font_num++;
12192  return 0;
12193  }
12194  NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
12195  cfg->ttf_data_owned_by_atlas = 1;
12196  }
12197  atlas->font_num++;
12198  return font;
12199 }
12200 
12201 NK_API struct nk_font*
12202 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
12203  nk_size size, float height, const struct nk_font_config *config)
12204 {
12205  struct nk_font_config cfg;
12206  NK_ASSERT(memory);
12207  NK_ASSERT(size);
12208 
12209  NK_ASSERT(atlas);
12210  NK_ASSERT(atlas->temporary.alloc);
12211  NK_ASSERT(atlas->temporary.free);
12212  NK_ASSERT(atlas->permanent.alloc);
12213  NK_ASSERT(atlas->permanent.free);
12214  if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
12215  !atlas->permanent.alloc || !atlas->permanent.free)
12216  return 0;
12217 
12218  cfg = (config) ? *config: nk_font_config(height);
12219  cfg.ttf_blob = memory;
12220  cfg.ttf_size = size;
12221  cfg.size = height;
12222  cfg.ttf_data_owned_by_atlas = 0;
12223  return nk_font_atlas_add(atlas, &cfg);
12224 }
12225 
12226 #ifdef NK_INCLUDE_STANDARD_IO
12227 NK_API struct nk_font*
12228 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
12229  float height, const struct nk_font_config *config)
12230 {
12231  nk_size size;
12232  char *memory;
12233  struct nk_font_config cfg;
12234 
12235  NK_ASSERT(atlas);
12236  NK_ASSERT(atlas->temporary.alloc);
12237  NK_ASSERT(atlas->temporary.free);
12238  NK_ASSERT(atlas->permanent.alloc);
12239  NK_ASSERT(atlas->permanent.free);
12240 
12241  if (!atlas || !file_path) return 0;
12242  memory = nk_file_load(file_path, &size, &atlas->permanent);
12243  if (!memory) return 0;
12244 
12245  cfg = (config) ? *config: nk_font_config(height);
12246  cfg.ttf_blob = memory;
12247  cfg.ttf_size = size;
12248  cfg.size = height;
12249  cfg.ttf_data_owned_by_atlas = 1;
12250  return nk_font_atlas_add(atlas, &cfg);
12251 }
12252 #endif
12253 
12254 NK_API struct nk_font*
12255 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
12256  void *compressed_data, nk_size compressed_size, float height,
12257  const struct nk_font_config *config)
12258 {
12259  unsigned int decompressed_size;
12260  void *decompressed_data;
12261  struct nk_font_config cfg;
12262 
12263  NK_ASSERT(atlas);
12264  NK_ASSERT(atlas->temporary.alloc);
12265  NK_ASSERT(atlas->temporary.free);
12266  NK_ASSERT(atlas->permanent.alloc);
12267  NK_ASSERT(atlas->permanent.free);
12268 
12269  NK_ASSERT(compressed_data);
12270  NK_ASSERT(compressed_size);
12271  if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
12272  !atlas->permanent.alloc || !atlas->permanent.free)
12273  return 0;
12274 
12275  decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
12276  decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
12277  NK_ASSERT(decompressed_data);
12278  if (!decompressed_data) return 0;
12279  nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
12280  (unsigned int)compressed_size);
12281 
12282  cfg = (config) ? *config: nk_font_config(height);
12283  cfg.ttf_blob = decompressed_data;
12284  cfg.ttf_size = decompressed_size;
12285  cfg.size = height;
12286  cfg.ttf_data_owned_by_atlas = 1;
12287  return nk_font_atlas_add(atlas, &cfg);
12288 }
12289 
12290 NK_API struct nk_font*
12291 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
12292  const char *data_base85, float height, const struct nk_font_config *config)
12293 {
12294  int compressed_size;
12295  void *compressed_data;
12296  struct nk_font *font;
12297 
12298  NK_ASSERT(atlas);
12299  NK_ASSERT(atlas->temporary.alloc);
12300  NK_ASSERT(atlas->temporary.free);
12301  NK_ASSERT(atlas->permanent.alloc);
12302  NK_ASSERT(atlas->permanent.free);
12303 
12304  NK_ASSERT(data_base85);
12305  if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
12306  !atlas->permanent.alloc || !atlas->permanent.free)
12307  return 0;
12308 
12309  compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
12310  compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
12311  NK_ASSERT(compressed_data);
12312  if (!compressed_data) return 0;
12313  nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
12314  font = nk_font_atlas_add_compressed(atlas, compressed_data,
12315  (nk_size)compressed_size, height, config);
12316  atlas->temporary.free(atlas->temporary.userdata, compressed_data);
12317  return font;
12318 }
12319 
12320 #ifdef NK_INCLUDE_DEFAULT_FONT
12321 NK_API struct nk_font*
12322 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
12323  float pixel_height, const struct nk_font_config *config)
12324 {
12325  NK_ASSERT(atlas);
12326  NK_ASSERT(atlas->temporary.alloc);
12327  NK_ASSERT(atlas->temporary.free);
12328  NK_ASSERT(atlas->permanent.alloc);
12329  NK_ASSERT(atlas->permanent.free);
12330  return nk_font_atlas_add_compressed_base85(atlas,
12331  nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
12332 }
12333 #endif
12334 
12335 NK_API const void*
12336 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
12337  enum nk_font_atlas_format fmt)
12338 {
12339  int i = 0;
12340  void *tmp = 0;
12341  nk_size tmp_size, img_size;
12342  struct nk_font *font_iter;
12343  struct nk_font_baker *baker;
12344 
12345  NK_ASSERT(atlas);
12346  NK_ASSERT(atlas->temporary.alloc);
12347  NK_ASSERT(atlas->temporary.free);
12348  NK_ASSERT(atlas->permanent.alloc);
12349  NK_ASSERT(atlas->permanent.free);
12350 
12351  NK_ASSERT(width);
12352  NK_ASSERT(height);
12353  if (!atlas || !width || !height ||
12354  !atlas->temporary.alloc || !atlas->temporary.free ||
12355  !atlas->permanent.alloc || !atlas->permanent.free)
12356  return 0;
12357 
12358 #ifdef NK_INCLUDE_DEFAULT_FONT
12359  /* no font added so just use default font */
12360  if (!atlas->font_num)
12361  atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
12362 #endif
12363  NK_ASSERT(atlas->font_num);
12364  if (!atlas->font_num) return 0;
12365 
12366  /* allocate temporary baker memory required for the baking process */
12367  nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
12368  tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
12369  NK_ASSERT(tmp);
12370  if (!tmp) goto failed;
12371 
12372  /* allocate glyph memory for all fonts */
12373  baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
12374  atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
12375  atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
12376  NK_ASSERT(atlas->glyphs);
12377  if (!atlas->glyphs)
12378  goto failed;
12379 
12380  /* pack all glyphs into a tight fit space */
12381  atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
12382  atlas->custom.h = NK_CURSOR_DATA_H + 1;
12383  if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
12384  atlas->config, atlas->font_num, &atlas->temporary))
12385  goto failed;
12386 
12387  /* allocate memory for the baked image font atlas */
12388  atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
12389  NK_ASSERT(atlas->pixel);
12390  if (!atlas->pixel)
12391  goto failed;
12392 
12393  /* bake glyphs and custom white pixel into image */
12394  nk_font_bake(baker, atlas->pixel, *width, *height,
12395  atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
12396  nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
12397  nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
12398 
12399  if (fmt == NK_FONT_ATLAS_RGBA32) {
12400  /* convert alpha8 image into rgba32 image */
12401  void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
12402  (nk_size)(*width * *height * 4));
12403  NK_ASSERT(img_rgba);
12404  if (!img_rgba) goto failed;
12405  nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
12406  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12407  atlas->pixel = img_rgba;
12408  }
12409  atlas->tex_width = *width;
12410  atlas->tex_height = *height;
12411 
12412  /* initialize each font */
12413  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12414  struct nk_font *font = font_iter;
12415  struct nk_font_config *config = font->config;
12416  nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
12417  config->font, nk_handle_ptr(0));
12418  }
12419 
12420  /* initialize each cursor */
12421  {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
12422  /* Pos ----- Size ------- Offset --*/
12423  {{ 0, 3}, {12,19}, { 0, 0}},
12424  {{13, 0}, { 7,16}, { 4, 8}},
12425  {{31, 0}, {23,23}, {11,11}},
12426  {{21, 0}, { 9, 23}, { 5,11}},
12427  {{55,18}, {23, 9}, {11, 5}},
12428  {{73, 0}, {17,17}, { 9, 9}},
12429  {{55, 0}, {17,17}, { 9, 9}}
12430  };
12431  for (i = 0; i < NK_CURSOR_COUNT; ++i) {
12432  struct nk_cursor *cursor = &atlas->cursors[i];
12433  cursor->img.w = (unsigned short)*width;
12434  cursor->img.h = (unsigned short)*height;
12435  cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
12436  cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
12437  cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
12438  cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
12439  cursor->size = nk_cursor_data[i][1];
12440  cursor->offset = nk_cursor_data[i][2];
12441  }}
12442  /* free temporary memory */
12443  atlas->temporary.free(atlas->temporary.userdata, tmp);
12444  return atlas->pixel;
12445 
12446 failed:
12447  /* error so cleanup all memory */
12448  if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
12449  if (atlas->glyphs) {
12450  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12451  atlas->glyphs = 0;
12452  }
12453  if (atlas->pixel) {
12454  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12455  atlas->pixel = 0;
12456  }
12457  return 0;
12458 }
12459 
12460 NK_API void
12461 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
12462  struct nk_draw_null_texture *null)
12463 {
12464  int i = 0;
12465  struct nk_font *font_iter;
12466  NK_ASSERT(atlas);
12467  if (!atlas) {
12468  if (!null) return;
12469  null->texture = texture;
12470  null->uv = nk_vec2(0.5f,0.5f);
12471  }
12472  if (null) {
12473  null->texture = texture;
12474  null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
12475  null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
12476  }
12477  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12478  font_iter->texture = texture;
12479 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12480  font_iter->handle.texture = texture;
12481 #endif
12482  }
12483  for (i = 0; i < NK_CURSOR_COUNT; ++i)
12484  atlas->cursors[i].img.handle = texture;
12485 
12486  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12487  atlas->pixel = 0;
12488  atlas->tex_width = 0;
12489  atlas->tex_height = 0;
12490  atlas->custom.x = 0;
12491  atlas->custom.y = 0;
12492  atlas->custom.w = 0;
12493  atlas->custom.h = 0;
12494 }
12495 
12496 NK_API void
12497 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
12498 {
12499  NK_ASSERT(atlas);
12500  NK_ASSERT(atlas->temporary.alloc);
12501  NK_ASSERT(atlas->temporary.free);
12502  NK_ASSERT(atlas->permanent.alloc);
12503  NK_ASSERT(atlas->permanent.free);
12504 
12505  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12506  if (atlas->config) {
12507  struct nk_font_config *iter, *next;
12508  for (iter = atlas->config; iter; iter = next) {
12509  next = iter->next;
12510  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
12511  atlas->permanent.free(atlas->permanent.userdata, iter);
12512  }
12513  atlas->config = 0;
12514  }
12515 }
12516 
12517 NK_API void
12518 nk_font_atlas_clear(struct nk_font_atlas *atlas)
12519 {
12520  NK_ASSERT(atlas);
12521  NK_ASSERT(atlas->temporary.alloc);
12522  NK_ASSERT(atlas->temporary.free);
12523  NK_ASSERT(atlas->permanent.alloc);
12524  NK_ASSERT(atlas->permanent.free);
12525  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12526 
12527  nk_font_atlas_cleanup(atlas);
12528  if (atlas->fonts) {
12529  struct nk_font *iter, *next;
12530  for (iter = atlas->fonts; iter; iter = next) {
12531  next = iter->next;
12532  atlas->permanent.free(atlas->permanent.userdata, iter);
12533  }
12534  atlas->fonts = 0;
12535  }
12536  if (atlas->glyphs)
12537  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12538  nk_zero_struct(*atlas);
12539 }
12540 #endif
12541 /* ==============================================================
12542  *
12543  * INPUT
12544  *
12545  * ===============================================================*/
12546 NK_API void
12547 nk_input_begin(struct nk_context *ctx)
12548 {
12549  int i;
12550  struct nk_input *in;
12551  NK_ASSERT(ctx);
12552  if (!ctx) return;
12553  in = &ctx->input;
12554  for (i = 0; i < NK_BUTTON_MAX; ++i)
12555  in->mouse.buttons[i].clicked = 0;
12556 
12557  in->keyboard.text_len = 0;
12558  in->mouse.scroll_delta = nk_vec2(0,0);
12559  in->mouse.prev.x = in->mouse.pos.x;
12560  in->mouse.prev.y = in->mouse.pos.y;
12561  in->mouse.delta.x = 0;
12562  in->mouse.delta.y = 0;
12563  for (i = 0; i < NK_KEY_MAX; i++)
12564  in->keyboard.keys[i].clicked = 0;
12565 }
12566 
12567 NK_API void
12568 nk_input_end(struct nk_context *ctx)
12569 {
12570  struct nk_input *in;
12571  NK_ASSERT(ctx);
12572  if (!ctx) return;
12573  in = &ctx->input;
12574  if (in->mouse.grab)
12575  in->mouse.grab = 0;
12576  if (in->mouse.ungrab) {
12577  in->mouse.grabbed = 0;
12578  in->mouse.ungrab = 0;
12579  in->mouse.grab = 0;
12580  }
12581 }
12582 
12583 NK_API void
12584 nk_input_motion(struct nk_context *ctx, int x, int y)
12585 {
12586  struct nk_input *in;
12587  NK_ASSERT(ctx);
12588  if (!ctx) return;
12589  in = &ctx->input;
12590  in->mouse.pos.x = (float)x;
12591  in->mouse.pos.y = (float)y;
12592  in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
12593  in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
12594 }
12595 
12596 NK_API void
12597 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
12598 {
12599  struct nk_input *in;
12600  NK_ASSERT(ctx);
12601  if (!ctx) return;
12602  in = &ctx->input;
12603  if (in->keyboard.keys[key].down != down)
12604  in->keyboard.keys[key].clicked++;
12605  in->keyboard.keys[key].down = down;
12606 }
12607 
12608 NK_API void
12609 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
12610 {
12611  struct nk_mouse_button *btn;
12612  struct nk_input *in;
12613  NK_ASSERT(ctx);
12614  if (!ctx) return;
12615  in = &ctx->input;
12616  if (in->mouse.buttons[id].down == down) return;
12617 
12618  btn = &in->mouse.buttons[id];
12619  btn->clicked_pos.x = (float)x;
12620  btn->clicked_pos.y = (float)y;
12621  btn->down = down;
12622  btn->clicked++;
12623 }
12624 
12625 NK_API void
12626 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
12627 {
12628  NK_ASSERT(ctx);
12629  if (!ctx) return;
12630  ctx->input.mouse.scroll_delta.x += val.x;
12631  ctx->input.mouse.scroll_delta.y += val.y;
12632 }
12633 
12634 NK_API void
12635 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
12636 {
12637  int len = 0;
12638  nk_rune unicode;
12639  struct nk_input *in;
12640 
12641  NK_ASSERT(ctx);
12642  if (!ctx) return;
12643  in = &ctx->input;
12644 
12645  len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
12646  if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
12647  nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
12649  in->keyboard.text_len += len;
12650  }
12651 }
12652 
12653 NK_API void
12654 nk_input_char(struct nk_context *ctx, char c)
12655 {
12656  nk_glyph glyph;
12657  NK_ASSERT(ctx);
12658  if (!ctx) return;
12659  glyph[0] = c;
12660  nk_input_glyph(ctx, glyph);
12661 }
12662 
12663 NK_API void
12664 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
12665 {
12666  nk_glyph rune;
12667  NK_ASSERT(ctx);
12668  if (!ctx) return;
12669  nk_utf_encode(unicode, rune, NK_UTF_SIZE);
12670  nk_input_glyph(ctx, rune);
12671 }
12672 
12673 NK_API int
12674 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
12675 {
12676  const struct nk_mouse_button *btn;
12677  if (!i) return nk_false;
12678  btn = &i->mouse.buttons[id];
12679  return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
12680 }
12681 
12682 NK_API int
12683 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12684  struct nk_rect b)
12685 {
12686  const struct nk_mouse_button *btn;
12687  if (!i) return nk_false;
12688  btn = &i->mouse.buttons[id];
12689  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
12690  return nk_false;
12691  return nk_true;
12692 }
12693 
12694 NK_API int
12696  struct nk_rect b, int down)
12697 {
12698  const struct nk_mouse_button *btn;
12699  if (!i) return nk_false;
12700  btn = &i->mouse.buttons[id];
12701  return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
12702 }
12703 
12704 NK_API int
12705 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12706  struct nk_rect b)
12707 {
12708  const struct nk_mouse_button *btn;
12709  if (!i) return nk_false;
12710  btn = &i->mouse.buttons[id];
12711  return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) &&
12712  btn->clicked) ? nk_true : nk_false;
12713 }
12714 
12715 NK_API int
12717  struct nk_rect b, int down)
12718 {
12719  const struct nk_mouse_button *btn;
12720  if (!i) return nk_false;
12721  btn = &i->mouse.buttons[id];
12722  return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
12723  btn->clicked) ? nk_true : nk_false;
12724 }
12725 
12726 NK_API int
12727 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
12728 {
12729  int i, down = 0;
12730  for (i = 0; i < NK_BUTTON_MAX; ++i)
12731  down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b);
12732  return down;
12733 }
12734 
12735 NK_API int
12736 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12737 {
12738  if (!i) return nk_false;
12739  return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
12740 }
12741 
12742 NK_API int
12743 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12744 {
12745  if (!i) return nk_false;
12746  return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
12747 }
12748 
12749 NK_API int
12750 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
12751 {
12752  if (!i) return nk_false;
12753  if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
12754  return nk_input_is_mouse_click_in_rect(i, id, rect);
12755 }
12756 
12757 NK_API int
12758 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
12759 {
12760  if (!i) return nk_false;
12761  return i->mouse.buttons[id].down;
12762 }
12763 
12764 NK_API int
12765 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
12766 {
12767  const struct nk_mouse_button *b;
12768  if (!i) return nk_false;
12769  b = &i->mouse.buttons[id];
12770  if (b->down && b->clicked)
12771  return nk_true;
12772  return nk_false;
12773 }
12774 
12775 NK_API int
12776 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
12777 {
12778  if (!i) return nk_false;
12779  return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
12780 }
12781 
12782 NK_API int
12783 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
12784 {
12785  const struct nk_key *k;
12786  if (!i) return nk_false;
12787  k = &i->keyboard.keys[key];
12788  if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
12789  return nk_true;
12790  return nk_false;
12791 }
12792 
12793 NK_API int
12794 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
12795 {
12796  const struct nk_key *k;
12797  if (!i) return nk_false;
12798  k = &i->keyboard.keys[key];
12799  if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
12800  return nk_true;
12801  return nk_false;
12802 }
12803 
12804 NK_API int
12805 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
12806 {
12807  const struct nk_key *k;
12808  if (!i) return nk_false;
12809  k = &i->keyboard.keys[key];
12810  if (k->down) return nk_true;
12811  return nk_false;
12812 }
12813 
12814 /*
12815  * ==============================================================
12816  *
12817  * TEXT EDITOR
12818  *
12819  * ===============================================================
12820  */
12821 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */
12822 struct nk_text_find {
12823  float x,y; /* position of n'th character */
12824  float height; /* height of line */
12825  int first_char, length; /* first char of row, and length */
12826  int prev_first; /*_ first char of previous row */
12827 };
12828 
12829 struct nk_text_edit_row {
12830  float x0,x1;
12831  /* starting x location, end x location (allows for align=right, etc) */
12832  float baseline_y_delta;
12833  /* position of baseline relative to previous row's baseline*/
12834  float ymin,ymax;
12835  /* height of row above and below baseline */
12836  int num_chars;
12837 };
12838 
12839 /* forward declarations */
12840 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
12841 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
12842 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
12843 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
12844 
12845 NK_INTERN float
12846 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
12847  const struct nk_user_font *font)
12848 {
12849  int len = 0;
12850  nk_rune unicode = 0;
12851  const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
12852  return font->width(font->userdata, font->height, str, len);
12853 }
12854 
12855 NK_INTERN void
12856 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
12857  int line_start_id, float row_height, const struct nk_user_font *font)
12858 {
12859  int l;
12860  int glyphs = 0;
12861  nk_rune unicode;
12862  const char *remaining;
12863  int len = nk_str_len_char(&edit->string);
12864  const char *end = nk_str_get_const(&edit->string) + len;
12865  const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
12866  const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
12867  text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
12868 
12869  r->x0 = 0.0f;
12870  r->x1 = size.x;
12871  r->baseline_y_delta = size.y;
12872  r->ymin = 0.0f;
12873  r->ymax = size.y;
12874  r->num_chars = glyphs;
12875 }
12876 
12877 NK_INTERN int
12878 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
12879  const struct nk_user_font *font, float row_height)
12880 {
12881  struct nk_text_edit_row r;
12882  int n = edit->string.len;
12883  float base_y = 0, prev_x;
12884  int i=0, k;
12885 
12886  r.x0 = r.x1 = 0;
12887  r.ymin = r.ymax = 0;
12888  r.num_chars = 0;
12889 
12890  /* search rows to find one that straddles 'y' */
12891  while (i < n) {
12892  nk_textedit_layout_row(&r, edit, i, row_height, font);
12893  if (r.num_chars <= 0)
12894  return n;
12895 
12896  if (i==0 && y < base_y + r.ymin)
12897  return 0;
12898 
12899  if (y < base_y + r.ymax)
12900  break;
12901 
12902  i += r.num_chars;
12903  base_y += r.baseline_y_delta;
12904  }
12905 
12906  /* below all text, return 'after' last character */
12907  if (i >= n)
12908  return n;
12909 
12910  /* check if it's before the beginning of the line */
12911  if (x < r.x0)
12912  return i;
12913 
12914  /* check if it's before the end of the line */
12915  if (x < r.x1) {
12916  /* search characters in row for one that straddles 'x' */
12917  k = i;
12918  prev_x = r.x0;
12919  for (i=0; i < r.num_chars; ++i) {
12920  float w = nk_textedit_get_width(edit, k, i, font);
12921  if (x < prev_x+w) {
12922  if (x < prev_x+w/2)
12923  return k+i;
12924  else return k+i+1;
12925  }
12926  prev_x += w;
12927  }
12928  /* shouldn't happen, but if it does, fall through to end-of-line case */
12929  }
12930 
12931  /* if the last character is a newline, return that.
12932  * otherwise return 'after' the last character */
12933  if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
12934  return i+r.num_chars-1;
12935  else return i+r.num_chars;
12936 }
12937 
12938 NK_INTERN void
12939 nk_textedit_click(struct nk_text_edit *state, float x, float y,
12940  const struct nk_user_font *font, float row_height)
12941 {
12942  /* API click: on mouse down, move the cursor to the clicked location,
12943  * and reset the selection */
12944  state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
12945  state->select_start = state->cursor;
12946  state->select_end = state->cursor;
12947  state->has_preferred_x = 0;
12948 }
12949 
12950 NK_INTERN void
12951 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
12952  const struct nk_user_font *font, float row_height)
12953 {
12954  /* API drag: on mouse drag, move the cursor and selection endpoint
12955  * to the clicked location */
12956  int p = nk_textedit_locate_coord(state, x, y, font, row_height);
12957  if (state->select_start == state->select_end)
12958  state->select_start = state->cursor;
12959  state->cursor = state->select_end = p;
12960 }
12961 
12962 NK_INTERN void
12963 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
12964  int n, int single_line, const struct nk_user_font *font, float row_height)
12965 {
12966  /* find the x/y location of a character, and remember info about the previous
12967  * row in case we get a move-up event (for page up, we'll have to rescan) */
12968  struct nk_text_edit_row r;
12969  int prev_start = 0;
12970  int z = state->string.len;
12971  int i=0, first;
12972 
12973  nk_zero_struct(r);
12974  if (n == z) {
12975  /* if it's at the end, then find the last line -- simpler than trying to
12976  explicitly handle this case in the regular code */
12977  nk_textedit_layout_row(&r, state, 0, row_height, font);
12978  if (single_line) {
12979  find->first_char = 0;
12980  find->length = z;
12981  } else {
12982  while (i < z) {
12983  prev_start = i;
12984  i += r.num_chars;
12985  nk_textedit_layout_row(&r, state, i, row_height, font);
12986  }
12987 
12988  find->first_char = i;
12989  find->length = r.num_chars;
12990  }
12991  find->x = r.x1;
12992  find->y = r.ymin;
12993  find->height = r.ymax - r.ymin;
12994  find->prev_first = prev_start;
12995  return;
12996  }
12997 
12998  /* search rows to find the one that straddles character n */
12999  find->y = 0;
13000 
13001  for(;;) {
13002  nk_textedit_layout_row(&r, state, i, row_height, font);
13003  if (n < i + r.num_chars) break;
13004  prev_start = i;
13005  i += r.num_chars;
13006  find->y += r.baseline_y_delta;
13007  }
13008 
13009  find->first_char = first = i;
13010  find->length = r.num_chars;
13011  find->height = r.ymax - r.ymin;
13012  find->prev_first = prev_start;
13013 
13014  /* now scan to find xpos */
13015  find->x = r.x0;
13016  for (i=0; first+i < n; ++i)
13017  find->x += nk_textedit_get_width(state, first, i, font);
13018 }
13019 
13020 NK_INTERN void
13021 nk_textedit_clamp(struct nk_text_edit *state)
13022 {
13023  /* make the selection/cursor state valid if client altered the string */
13024  int n = state->string.len;
13025  if (NK_TEXT_HAS_SELECTION(state)) {
13026  if (state->select_start > n) state->select_start = n;
13027  if (state->select_end > n) state->select_end = n;
13028  /* if clamping forced them to be equal, move the cursor to match */
13029  if (state->select_start == state->select_end)
13030  state->cursor = state->select_start;
13031  }
13032  if (state->cursor > n) state->cursor = n;
13033 }
13034 
13035 NK_API void
13036 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
13037 {
13038  /* delete characters while updating undo */
13039  nk_textedit_makeundo_delete(state, where, len);
13040  nk_str_delete_runes(&state->string, where, len);
13041  state->has_preferred_x = 0;
13042 }
13043 
13044 NK_API void
13046 {
13047  /* delete the section */
13048  nk_textedit_clamp(state);
13049  if (NK_TEXT_HAS_SELECTION(state)) {
13050  if (state->select_start < state->select_end) {
13051  nk_textedit_delete(state, state->select_start,
13052  state->select_end - state->select_start);
13053  state->select_end = state->cursor = state->select_start;
13054  } else {
13055  nk_textedit_delete(state, state->select_end,
13056  state->select_start - state->select_end);
13057  state->select_start = state->cursor = state->select_end;
13058  }
13059  state->has_preferred_x = 0;
13060  }
13061 }
13062 
13063 NK_INTERN void
13064 nk_textedit_sortselection(struct nk_text_edit *state)
13065 {
13066  /* canonicalize the selection so start <= end */
13067  if (state->select_end < state->select_start) {
13068  int temp = state->select_end;
13069  state->select_end = state->select_start;
13070  state->select_start = temp;
13071  }
13072 }
13073 
13074 NK_INTERN void
13075 nk_textedit_move_to_first(struct nk_text_edit *state)
13076 {
13077  /* move cursor to first character of selection */
13078  if (NK_TEXT_HAS_SELECTION(state)) {
13079  nk_textedit_sortselection(state);
13080  state->cursor = state->select_start;
13081  state->select_end = state->select_start;
13082  state->has_preferred_x = 0;
13083  }
13084 }
13085 
13086 NK_INTERN void
13087 nk_textedit_move_to_last(struct nk_text_edit *state)
13088 {
13089  /* move cursor to last character of selection */
13090  if (NK_TEXT_HAS_SELECTION(state)) {
13091  nk_textedit_sortselection(state);
13092  nk_textedit_clamp(state);
13093  state->cursor = state->select_end;
13094  state->select_start = state->select_end;
13095  state->has_preferred_x = 0;
13096  }
13097 }
13098 
13099 NK_INTERN int
13100 nk_is_word_boundary( struct nk_text_edit *state, int idx)
13101 {
13102  int len;
13103  nk_rune c;
13104  if (idx <= 0) return 1;
13105  if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
13106  return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
13107  c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
13108  c == '|');
13109 }
13110 
13111 NK_INTERN int
13112 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
13113 {
13114  int c = state->cursor - 1;
13115  while( c >= 0 && !nk_is_word_boundary(state, c))
13116  --c;
13117 
13118  if( c < 0 )
13119  c = 0;
13120 
13121  return c;
13122 }
13123 
13124 NK_INTERN int
13125 nk_textedit_move_to_word_next(struct nk_text_edit *state)
13126 {
13127  const int len = state->string.len;
13128  int c = state->cursor+1;
13129  while( c < len && !nk_is_word_boundary(state, c))
13130  ++c;
13131 
13132  if( c > len )
13133  c = len;
13134 
13135  return c;
13136 }
13137 
13138 NK_INTERN void
13139 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
13140 {
13141  /* update selection and cursor to match each other */
13142  if (!NK_TEXT_HAS_SELECTION(state))
13143  state->select_start = state->select_end = state->cursor;
13144  else state->cursor = state->select_end;
13145 }
13146 
13147 NK_API int
13148 nk_textedit_cut(struct nk_text_edit *state)
13149 {
13150  /* API cut: delete selection */
13151  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13152  return 0;
13153  if (NK_TEXT_HAS_SELECTION(state)) {
13154  nk_textedit_delete_selection(state); /* implicitly clamps */
13155  state->has_preferred_x = 0;
13156  return 1;
13157  }
13158  return 0;
13159 }
13160 
13161 NK_API int
13162 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
13163 {
13164  /* API paste: replace existing selection with passed-in text */
13165  int glyphs;
13166  const char *text = (const char *) ctext;
13167  if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
13168 
13169  /* if there's a selection, the paste should delete it */
13170  nk_textedit_clamp(state);
13172 
13173  /* try to insert the characters */
13174  glyphs = nk_utf_len(ctext, len);
13175  if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
13176  nk_textedit_makeundo_insert(state, state->cursor, glyphs);
13177  state->cursor += len;
13178  state->has_preferred_x = 0;
13179  return 1;
13180  }
13181  /* remove the undo since we didn't actually insert the characters */
13182  if (state->undo.undo_point)
13183  --state->undo.undo_point;
13184  return 0;
13185 }
13186 
13187 NK_API void
13188 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
13189 {
13190  nk_rune unicode;
13191  int glyph_len;
13192  int text_len = 0;
13193 
13194  NK_ASSERT(state);
13195  NK_ASSERT(text);
13196  if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
13197 
13198  glyph_len = nk_utf_decode(text, &unicode, total_len);
13199  while ((text_len < total_len) && glyph_len)
13200  {
13201  /* don't insert a backward delete, just process the event */
13202  if (unicode == 127) goto next;
13203  /* can't add newline in single-line mode */
13204  if (unicode == '\n' && state->single_line) goto next;
13205  /* filter incoming text */
13206  if (state->filter && !state->filter(state, unicode)) goto next;
13207 
13208  if (!NK_TEXT_HAS_SELECTION(state) &&
13209  state->cursor < state->string.len)
13210  {
13211  if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
13212  nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
13213  nk_str_delete_runes(&state->string, state->cursor, 1);
13214  }
13215  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13216  text+text_len, 1))
13217  {
13218  ++state->cursor;
13219  state->has_preferred_x = 0;
13220  }
13221  } else {
13222  nk_textedit_delete_selection(state); /* implicitly clamps */
13223  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13224  text+text_len, 1))
13225  {
13226  nk_textedit_makeundo_insert(state, state->cursor, 1);
13227  ++state->cursor;
13228  state->has_preferred_x = 0;
13229  }
13230  }
13231  next:
13232  text_len += glyph_len;
13233  glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
13234  }
13235 }
13236 
13237 NK_INTERN void
13238 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
13239  const struct nk_user_font *font, float row_height)
13240 {
13241 retry:
13242  switch (key)
13243  {
13244  case NK_KEY_NONE:
13245  case NK_KEY_CTRL:
13246  case NK_KEY_ENTER:
13247  case NK_KEY_SHIFT:
13248  case NK_KEY_TAB:
13249  case NK_KEY_COPY:
13250  case NK_KEY_CUT:
13251  case NK_KEY_PASTE:
13252  case NK_KEY_MAX:
13253  default: break;
13254  case NK_KEY_TEXT_UNDO:
13255  nk_textedit_undo(state);
13256  state->has_preferred_x = 0;
13257  break;
13258 
13259  case NK_KEY_TEXT_REDO:
13260  nk_textedit_redo(state);
13261  state->has_preferred_x = 0;
13262  break;
13263 
13265  nk_textedit_select_all(state);
13266  state->has_preferred_x = 0;
13267  break;
13268 
13270  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13271  state->mode = NK_TEXT_EDIT_MODE_INSERT;
13272  break;
13274  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13276  break;
13278  if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
13279  state->mode == NK_TEXT_EDIT_MODE_REPLACE)
13280  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13281  break;
13282 
13283  case NK_KEY_LEFT:
13284  if (shift_mod) {
13285  nk_textedit_clamp(state);
13286  nk_textedit_prep_selection_at_cursor(state);
13287  /* move selection left */
13288  if (state->select_end > 0)
13289  --state->select_end;
13290  state->cursor = state->select_end;
13291  state->has_preferred_x = 0;
13292  } else {
13293  /* if currently there's a selection,
13294  * move cursor to start of selection */
13295  if (NK_TEXT_HAS_SELECTION(state))
13296  nk_textedit_move_to_first(state);
13297  else if (state->cursor > 0)
13298  --state->cursor;
13299  state->has_preferred_x = 0;
13300  } break;
13301 
13302  case NK_KEY_RIGHT:
13303  if (shift_mod) {
13304  nk_textedit_prep_selection_at_cursor(state);
13305  /* move selection right */
13306  ++state->select_end;
13307  nk_textedit_clamp(state);
13308  state->cursor = state->select_end;
13309  state->has_preferred_x = 0;
13310  } else {
13311  /* if currently there's a selection,
13312  * move cursor to end of selection */
13313  if (NK_TEXT_HAS_SELECTION(state))
13314  nk_textedit_move_to_last(state);
13315  else ++state->cursor;
13316  nk_textedit_clamp(state);
13317  state->has_preferred_x = 0;
13318  } break;
13319 
13320  case NK_KEY_TEXT_WORD_LEFT:
13321  if (shift_mod) {
13322  if( !NK_TEXT_HAS_SELECTION( state ) )
13323  nk_textedit_prep_selection_at_cursor(state);
13324  state->cursor = nk_textedit_move_to_word_previous(state);
13325  state->select_end = state->cursor;
13326  nk_textedit_clamp(state );
13327  } else {
13328  if (NK_TEXT_HAS_SELECTION(state))
13329  nk_textedit_move_to_first(state);
13330  else {
13331  state->cursor = nk_textedit_move_to_word_previous(state);
13332  nk_textedit_clamp(state );
13333  }
13334  } break;
13335 
13337  if (shift_mod) {
13338  if( !NK_TEXT_HAS_SELECTION( state ) )
13339  nk_textedit_prep_selection_at_cursor(state);
13340  state->cursor = nk_textedit_move_to_word_next(state);
13341  state->select_end = state->cursor;
13342  nk_textedit_clamp(state);
13343  } else {
13344  if (NK_TEXT_HAS_SELECTION(state))
13345  nk_textedit_move_to_last(state);
13346  else {
13347  state->cursor = nk_textedit_move_to_word_next(state);
13348  nk_textedit_clamp(state );
13349  }
13350  } break;
13351 
13352  case NK_KEY_DOWN: {
13353  struct nk_text_find find;
13354  struct nk_text_edit_row row;
13355  int i, sel = shift_mod;
13356 
13357  if (state->single_line) {
13358  /* on windows, up&down in single-line behave like left&right */
13359  key = NK_KEY_RIGHT;
13360  goto retry;
13361  }
13362 
13363  if (sel)
13364  nk_textedit_prep_selection_at_cursor(state);
13365  else if (NK_TEXT_HAS_SELECTION(state))
13366  nk_textedit_move_to_last(state);
13367 
13368  /* compute current position of cursor point */
13369  nk_textedit_clamp(state);
13370  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13371  font, row_height);
13372 
13373  /* now find character position down a row */
13374  if (find.length)
13375  {
13376  float x;
13377  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13378  int start = find.first_char + find.length;
13379 
13380  state->cursor = start;
13381  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13382  x = row.x0;
13383 
13384  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13385  float dx = nk_textedit_get_width(state, start, i, font);
13386  x += dx;
13387  if (x > goal_x)
13388  break;
13389  ++state->cursor;
13390  }
13391  nk_textedit_clamp(state);
13392 
13393  state->has_preferred_x = 1;
13394  state->preferred_x = goal_x;
13395  if (sel)
13396  state->select_end = state->cursor;
13397  }
13398  } break;
13399 
13400  case NK_KEY_UP: {
13401  struct nk_text_find find;
13402  struct nk_text_edit_row row;
13403  int i, sel = shift_mod;
13404 
13405  if (state->single_line) {
13406  /* on windows, up&down become left&right */
13407  key = NK_KEY_LEFT;
13408  goto retry;
13409  }
13410 
13411  if (sel)
13412  nk_textedit_prep_selection_at_cursor(state);
13413  else if (NK_TEXT_HAS_SELECTION(state))
13414  nk_textedit_move_to_first(state);
13415 
13416  /* compute current position of cursor point */
13417  nk_textedit_clamp(state);
13418  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13419  font, row_height);
13420 
13421  /* can only go up if there's a previous row */
13422  if (find.prev_first != find.first_char) {
13423  /* now find character position up a row */
13424  float x;
13425  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13426 
13427  state->cursor = find.prev_first;
13428  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13429  x = row.x0;
13430 
13431  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13432  float dx = nk_textedit_get_width(state, find.prev_first, i, font);
13433  x += dx;
13434  if (x > goal_x)
13435  break;
13436  ++state->cursor;
13437  }
13438  nk_textedit_clamp(state);
13439 
13440  state->has_preferred_x = 1;
13441  state->preferred_x = goal_x;
13442  if (sel) state->select_end = state->cursor;
13443  }
13444  } break;
13445 
13446  case NK_KEY_DEL:
13447  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13448  break;
13449  if (NK_TEXT_HAS_SELECTION(state))
13451  else {
13452  int n = state->string.len;
13453  if (state->cursor < n)
13454  nk_textedit_delete(state, state->cursor, 1);
13455  }
13456  state->has_preferred_x = 0;
13457  break;
13458 
13459  case NK_KEY_BACKSPACE:
13460  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13461  break;
13462  if (NK_TEXT_HAS_SELECTION(state))
13464  else {
13465  nk_textedit_clamp(state);
13466  if (state->cursor > 0) {
13467  nk_textedit_delete(state, state->cursor-1, 1);
13468  --state->cursor;
13469  }
13470  }
13471  state->has_preferred_x = 0;
13472  break;
13473 
13474  case NK_KEY_TEXT_START:
13475  if (shift_mod) {
13476  nk_textedit_prep_selection_at_cursor(state);
13477  state->cursor = state->select_end = 0;
13478  state->has_preferred_x = 0;
13479  } else {
13480  state->cursor = state->select_start = state->select_end = 0;
13481  state->has_preferred_x = 0;
13482  }
13483  break;
13484 
13485  case NK_KEY_TEXT_END:
13486  if (shift_mod) {
13487  nk_textedit_prep_selection_at_cursor(state);
13488  state->cursor = state->select_end = state->string.len;
13489  state->has_preferred_x = 0;
13490  } else {
13491  state->cursor = state->string.len;
13492  state->select_start = state->select_end = 0;
13493  state->has_preferred_x = 0;
13494  }
13495  break;
13496 
13497  case NK_KEY_TEXT_LINE_START: {
13498  if (shift_mod) {
13499  struct nk_text_find find;
13500  nk_textedit_clamp(state);
13501  nk_textedit_prep_selection_at_cursor(state);
13502  if (state->string.len && state->cursor == state->string.len)
13503  --state->cursor;
13504  nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
13505  font, row_height);
13506  state->cursor = state->select_end = find.first_char;
13507  state->has_preferred_x = 0;
13508  } else {
13509  struct nk_text_find find;
13510  if (state->string.len && state->cursor == state->string.len)
13511  --state->cursor;
13512  nk_textedit_clamp(state);
13513  nk_textedit_move_to_first(state);
13514  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13515  font, row_height);
13516  state->cursor = find.first_char;
13517  state->has_preferred_x = 0;
13518  }
13519  } break;
13520 
13521  case NK_KEY_TEXT_LINE_END: {
13522  if (shift_mod) {
13523  struct nk_text_find find;
13524  nk_textedit_clamp(state);
13525  nk_textedit_prep_selection_at_cursor(state);
13526  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13527  font, row_height);
13528  state->has_preferred_x = 0;
13529  state->cursor = find.first_char + find.length;
13530  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13531  --state->cursor;
13532  state->select_end = state->cursor;
13533  } else {
13534  struct nk_text_find find;
13535  nk_textedit_clamp(state);
13536  nk_textedit_move_to_first(state);
13537  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13538  font, row_height);
13539 
13540  state->has_preferred_x = 0;
13541  state->cursor = find.first_char + find.length;
13542  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13543  --state->cursor;
13544  }} break;
13545  }
13546 }
13547 
13548 NK_INTERN void
13549 nk_textedit_flush_redo(struct nk_text_undo_state *state)
13550 {
13553 }
13554 
13555 NK_INTERN void
13556 nk_textedit_discard_undo(struct nk_text_undo_state *state)
13557 {
13558  /* discard the oldest entry in the undo list */
13559  if (state->undo_point > 0) {
13560  /* if the 0th undo state has characters, clean those up */
13561  if (state->undo_rec[0].char_storage >= 0) {
13562  int n = state->undo_rec[0].insert_length, i;
13563  /* delete n characters from all other records */
13564  state->undo_char_point = (short)(state->undo_char_point - n);
13565  NK_MEMCPY(state->undo_char, state->undo_char + n,
13566  (nk_size)state->undo_char_point*sizeof(nk_rune));
13567  for (i=0; i < state->undo_point; ++i) {
13568  if (state->undo_rec[i].char_storage >= 0)
13569  state->undo_rec[i].char_storage = (short)
13570  (state->undo_rec[i].char_storage - n);
13571  }
13572  }
13573  --state->undo_point;
13574  NK_MEMCPY(state->undo_rec, state->undo_rec+1,
13575  (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
13576  }
13577 }
13578 
13579 NK_INTERN void
13580 nk_textedit_discard_redo(struct nk_text_undo_state *state)
13581 {
13582 /* discard the oldest entry in the redo list--it's bad if this
13583  ever happens, but because undo & redo have to store the actual
13584  characters in different cases, the redo character buffer can
13585  fill up even though the undo buffer didn't */
13586  nk_size num;
13587  int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
13588  if (state->redo_point <= k) {
13589  /* if the k'th undo state has characters, clean those up */
13590  if (state->undo_rec[k].char_storage >= 0) {
13591  int n = state->undo_rec[k].insert_length, i;
13592  /* delete n characters from all other records */
13593  state->redo_char_point = (short)(state->redo_char_point + n);
13595  NK_MEMCPY(state->undo_char + state->redo_char_point,
13596  state->undo_char + state->redo_char_point-n, num * sizeof(char));
13597  for (i = state->redo_point; i < k; ++i) {
13598  if (state->undo_rec[i].char_storage >= 0) {
13599  state->undo_rec[i].char_storage = (short)
13600  (state->undo_rec[i].char_storage + n);
13601  }
13602  }
13603  }
13604  ++state->redo_point;
13605  num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
13606  if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
13607  state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
13608  }
13609 }
13610 
13612 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
13613 {
13614  /* any time we create a new undo record, we discard redo*/
13615  nk_textedit_flush_redo(state);
13616 
13617  /* if we have no free records, we have to make room,
13618  * by sliding the existing records down */
13619  if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13620  nk_textedit_discard_undo(state);
13621 
13622  /* if the characters to store won't possibly fit in the buffer,
13623  * we can't undo */
13624  if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
13625  state->undo_point = 0;
13626  state->undo_char_point = 0;
13627  return 0;
13628  }
13629 
13630  /* if we don't have enough free characters in the buffer,
13631  * we have to make room */
13632  while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
13633  nk_textedit_discard_undo(state);
13634  return &state->undo_rec[state->undo_point++];
13635 }
13636 
13637 NK_INTERN nk_rune*
13638 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
13639  int insert_len, int delete_len)
13640 {
13641  struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
13642  if (r == 0)
13643  return 0;
13644 
13645  r->where = pos;
13646  r->insert_length = (short) insert_len;
13647  r->delete_length = (short) delete_len;
13648 
13649  if (insert_len == 0) {
13650  r->char_storage = -1;
13651  return 0;
13652  } else {
13653  r->char_storage = state->undo_char_point;
13654  state->undo_char_point = (short)(state->undo_char_point + insert_len);
13655  return &state->undo_char[r->char_storage];
13656  }
13657 }
13658 
13659 NK_API void
13660 nk_textedit_undo(struct nk_text_edit *state)
13661 {
13662  struct nk_text_undo_state *s = &state->undo;
13663  struct nk_text_undo_record u, *r;
13664  if (s->undo_point == 0)
13665  return;
13666 
13667  /* we need to do two things: apply the undo record, and create a redo record */
13668  u = s->undo_rec[s->undo_point-1];
13669  r = &s->undo_rec[s->redo_point-1];
13670  r->char_storage = -1;
13671 
13672  r->insert_length = u.delete_length;
13673  r->delete_length = u.insert_length;
13674  r->where = u.where;
13675 
13676  if (u.delete_length)
13677  {
13678  /* if the undo record says to delete characters, then the redo record will
13679  need to re-insert the characters that get deleted, so we need to store
13680  them.
13681  there are three cases:
13682  - there's enough room to store the characters
13683  - characters stored for *redoing* don't leave room for redo
13684  - characters stored for *undoing* don't leave room for redo
13685  if the last is true, we have to bail */
13686  if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
13687  /* the undo records take up too much character space; there's no space
13688  * to store the redo characters */
13689  r->insert_length = 0;
13690  } else {
13691  int i;
13692  /* there's definitely room to store the characters eventually */
13693  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
13694  /* there's currently not enough room, so discard a redo record */
13695  nk_textedit_discard_redo(s);
13696  /* should never happen: */
13698  return;
13699  }
13700 
13701  r = &s->undo_rec[s->redo_point-1];
13702  r->char_storage = (short)(s->redo_char_point - u.delete_length);
13703  s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
13704 
13705  /* now save the characters */
13706  for (i=0; i < u.delete_length; ++i)
13707  s->undo_char[r->char_storage + i] =
13708  nk_str_rune_at(&state->string, u.where + i);
13709  }
13710  /* now we can carry out the deletion */
13711  nk_str_delete_runes(&state->string, u.where, u.delete_length);
13712  }
13713 
13714  /* check type of recorded action: */
13715  if (u.insert_length) {
13716  /* easy case: was a deletion, so we need to insert n characters */
13717  nk_str_insert_text_runes(&state->string, u.where,
13718  &s->undo_char[u.char_storage], u.insert_length);
13719  s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
13720  }
13721  state->cursor = (short)(u.where + u.insert_length);
13722 
13723  s->undo_point--;
13724  s->redo_point--;
13725 }
13726 
13727 NK_API void
13728 nk_textedit_redo(struct nk_text_edit *state)
13729 {
13730  struct nk_text_undo_state *s = &state->undo;
13731  struct nk_text_undo_record *u, r;
13733  return;
13734 
13735  /* we need to do two things: apply the redo record, and create an undo record */
13736  u = &s->undo_rec[s->undo_point];
13737  r = s->undo_rec[s->redo_point];
13738 
13739  /* we KNOW there must be room for the undo record, because the redo record
13740  was derived from an undo record */
13743  u->where = r.where;
13744  u->char_storage = -1;
13745 
13746  if (r.delete_length) {
13747  /* the redo record requires us to delete characters, so the undo record
13748  needs to store the characters */
13749  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
13750  u->insert_length = 0;
13751  u->delete_length = 0;
13752  } else {
13753  int i;
13754  u->char_storage = s->undo_char_point;
13755  s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
13756 
13757  /* now save the characters */
13758  for (i=0; i < u->insert_length; ++i) {
13759  s->undo_char[u->char_storage + i] =
13760  nk_str_rune_at(&state->string, u->where + i);
13761  }
13762  }
13764  }
13765 
13766  if (r.insert_length) {
13767  /* easy case: need to insert n characters */
13770  }
13771  state->cursor = r.where + r.insert_length;
13772 
13773  s->undo_point++;
13774  s->redo_point++;
13775 }
13776 
13777 NK_INTERN void
13778 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
13779 {
13780  nk_textedit_createundo(&state->undo, where, 0, length);
13781 }
13782 
13783 NK_INTERN void
13784 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
13785 {
13786  int i;
13787  nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
13788  if (p) {
13789  for (i=0; i < length; ++i)
13790  p[i] = nk_str_rune_at(&state->string, where+i);
13791  }
13792 }
13793 
13794 NK_INTERN void
13795 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
13796  int old_length, int new_length)
13797 {
13798  int i;
13799  nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
13800  if (p) {
13801  for (i=0; i < old_length; ++i)
13802  p[i] = nk_str_rune_at(&state->string, where+i);
13803  }
13804 }
13805 
13806 NK_INTERN void
13807 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
13808  nk_plugin_filter filter)
13809 {
13810  /* reset the state to default */
13811  state->undo.undo_point = 0;
13812  state->undo.undo_char_point = 0;
13815  state->select_end = state->select_start = 0;
13816  state->cursor = 0;
13817  state->has_preferred_x = 0;
13818  state->preferred_x = 0;
13819  state->cursor_at_end_of_line = 0;
13820  state->initialized = 1;
13821  state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
13822  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13823  state->filter = filter;
13824  state->scrollbar = nk_vec2(0,0);
13825 }
13826 
13827 NK_API void
13828 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
13829 {
13830  NK_ASSERT(state);
13831  NK_ASSERT(memory);
13832  if (!state || !memory || !size) return;
13833  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13834  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13835  nk_str_init_fixed(&state->string, memory, size);
13836 }
13837 
13838 NK_API void
13839 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size)
13840 {
13841  NK_ASSERT(state);
13842  NK_ASSERT(alloc);
13843  if (!state || !alloc) return;
13844  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13845  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13846  nk_str_init(&state->string, alloc, size);
13847 }
13848 
13849 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13850 NK_API void
13851 nk_textedit_init_default(struct nk_text_edit *state)
13852 {
13853  NK_ASSERT(state);
13854  if (!state) return;
13855  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13856  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13857  nk_str_init_default(&state->string);
13858 }
13859 #endif
13860 
13861 NK_API void
13862 nk_textedit_select_all(struct nk_text_edit *state)
13863 {
13864  NK_ASSERT(state);
13865  state->select_start = 0;
13866  state->select_end = state->string.len;
13867 }
13868 
13869 NK_API void
13870 nk_textedit_free(struct nk_text_edit *state)
13871 {
13872  NK_ASSERT(state);
13873  if (!state) return;
13874  nk_str_free(&state->string);
13875 }
13876 
13877 /* ===============================================================
13878  *
13879  * TEXT WIDGET
13880  *
13881  * ===============================================================*/
13882 #define nk_widget_state_reset(s)\
13883  if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
13884  (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
13885  else (*(s)) = NK_WIDGET_STATE_INACTIVE;
13886 
13887 struct nk_text {
13888  struct nk_vec2 padding;
13889  struct nk_color background;
13890  struct nk_color text;
13891 };
13892 
13893 NK_INTERN void
13894 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
13895  const char *string, int len, const struct nk_text *t,
13896  nk_flags a, const struct nk_user_font *f)
13897 {
13898  struct nk_rect label;
13899  float text_width;
13900 
13901  NK_ASSERT(o);
13902  NK_ASSERT(t);
13903  if (!o || !t) return;
13904 
13905  b.h = NK_MAX(b.h, 2 * t->padding.y);
13906  label.x = 0; label.w = 0;
13907  label.y = b.y + t->padding.y;
13908  label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
13909 
13910  text_width = f->width(f->userdata, f->height, (const char*)string, len);
13911  text_width += (2.0f * t->padding.x);
13912 
13913  /* align in x-axis */
13914  if (a & NK_TEXT_ALIGN_LEFT) {
13915  label.x = b.x + t->padding.x;
13916  label.w = NK_MAX(0, b.w - 2 * t->padding.x);
13917  } else if (a & NK_TEXT_ALIGN_CENTERED) {
13918  label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
13919  label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
13920  label.x = NK_MAX(b.x + t->padding.x, label.x);
13921  label.w = NK_MIN(b.x + b.w, label.x + label.w);
13922  if (label.w >= label.x) label.w -= label.x;
13923  } else if (a & NK_TEXT_ALIGN_RIGHT) {
13924  label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
13925  label.w = (float)text_width + 2 * t->padding.x;
13926  } else return;
13927 
13928  /* align in y-axis */
13929  if (a & NK_TEXT_ALIGN_MIDDLE) {
13930  label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
13931  label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
13932  } else if (a & NK_TEXT_ALIGN_BOTTOM) {
13933  label.y = b.y + b.h - f->height;
13934  label.h = f->height;
13935  }
13936  nk_draw_text(o, label, (const char*)string,
13937  len, f, t->background, t->text);
13938 }
13939 
13940 NK_INTERN void
13941 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
13942  const char *string, int len, const struct nk_text *t,
13943  const struct nk_user_font *f)
13944 {
13945  float width;
13946  int glyphs = 0;
13947  int fitting = 0;
13948  int done = 0;
13949  struct nk_rect line;
13950  struct nk_text text;
13951  NK_INTERN nk_rune seperator[] = {' '};
13952 
13953  NK_ASSERT(o);
13954  NK_ASSERT(t);
13955  if (!o || !t) return;
13956 
13957  text.padding = nk_vec2(0,0);
13958  text.background = t->background;
13959  text.text = t->text;
13960 
13961  b.w = NK_MAX(b.w, 2 * t->padding.x);
13962  b.h = NK_MAX(b.h, 2 * t->padding.y);
13963  b.h = b.h - 2 * t->padding.y;
13964 
13965  line.x = b.x + t->padding.x;
13966  line.y = b.y + t->padding.y;
13967  line.w = b.w - 2 * t->padding.x;
13968  line.h = 2 * t->padding.y + f->height;
13969 
13970  fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13971  while (done < len) {
13972  if (!fitting || line.y + line.h >= (b.y + b.h)) break;
13973  nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
13974  done += fitting;
13975  line.y += f->height + 2 * t->padding.y;
13976  fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13977  }
13978 }
13979 
13980 /* ===============================================================
13981  *
13982  * BUTTON
13983  *
13984  * ===============================================================*/
13985 NK_INTERN void
13986 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
13987  struct nk_rect content, struct nk_color background, struct nk_color foreground,
13988  float border_width, const struct nk_user_font *font)
13989 {
13990  switch (type) {
13991  case NK_SYMBOL_X:
13992  case NK_SYMBOL_UNDERSCORE:
13993  case NK_SYMBOL_PLUS:
13994  case NK_SYMBOL_MINUS: {
13995  /* single character text symbol */
13996  const char *X = (type == NK_SYMBOL_X) ? "x":
13997  (type == NK_SYMBOL_UNDERSCORE) ? "_":
13998  (type == NK_SYMBOL_PLUS) ? "+": "-";
13999  struct nk_text text;
14000  text.padding = nk_vec2(0,0);
14001  text.background = background;
14002  text.text = foreground;
14003  nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
14004  } break;
14007  case NK_SYMBOL_RECT_SOLID:
14008  case NK_SYMBOL_RECT_OUTLINE: {
14009  /* simple empty/filled shapes */
14010  if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) {
14011  nk_fill_rect(out, content, 0, foreground);
14012  if (type == NK_SYMBOL_RECT_OUTLINE)
14013  nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
14014  } else {
14015  nk_fill_circle(out, content, foreground);
14016  if (type == NK_SYMBOL_CIRCLE_OUTLINE)
14017  nk_fill_circle(out, nk_shrink_rect(content, 1), background);
14018  }
14019  } break;
14020  case NK_SYMBOL_TRIANGLE_UP:
14023  case NK_SYMBOL_TRIANGLE_RIGHT: {
14024  enum nk_heading heading;
14025  struct nk_vec2 points[3];
14026  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
14027  (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT:
14028  (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN;
14029  nk_triangle_from_direction(points, content, 0, 0, heading);
14030  nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
14031  points[2].x, points[2].y, foreground);
14032  } break;
14033  default:
14034  case NK_SYMBOL_NONE:
14035  case NK_SYMBOL_MAX: break;
14036  }
14037 }
14038 
14039 NK_INTERN int
14040 nk_button_behavior(nk_flags *state, struct nk_rect r,
14041  const struct nk_input *i, enum nk_button_behavior behavior)
14042 {
14043  int ret = 0;
14044  nk_widget_state_reset(state);
14045  if (!i) return 0;
14046  if (nk_input_is_mouse_hovering_rect(i, r)) {
14047  *state = NK_WIDGET_STATE_HOVERED;
14049  *state = NK_WIDGET_STATE_ACTIVE;
14051  ret = (behavior != NK_BUTTON_DEFAULT) ?
14053 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
14055 #else
14057 #endif
14058  }
14059  }
14061  *state |= NK_WIDGET_STATE_ENTERED;
14062  else if (nk_input_is_mouse_prev_hovering_rect(i, r))
14063  *state |= NK_WIDGET_STATE_LEFT;
14064  return ret;
14065 }
14066 
14067 NK_INTERN const struct nk_style_item*
14068 nk_draw_button(struct nk_command_buffer *out,
14069  const struct nk_rect *bounds, nk_flags state,
14070  const struct nk_style_button *style)
14071 {
14072  const struct nk_style_item *background;
14073  if (state & NK_WIDGET_STATE_HOVER)
14074  background = &style->hover;
14075  else if (state & NK_WIDGET_STATE_ACTIVED)
14076  background = &style->active;
14077  else background = &style->normal;
14078 
14079  if (background->type == NK_STYLE_ITEM_IMAGE) {
14080  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14081  } else {
14082  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14083  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14084  }
14085  return background;
14086 }
14087 
14088 NK_INTERN int
14089 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
14090  const struct nk_style_button *style, const struct nk_input *in,
14091  enum nk_button_behavior behavior, struct nk_rect *content)
14092 {
14093  struct nk_rect bounds;
14094  NK_ASSERT(style);
14095  NK_ASSERT(state);
14096  NK_ASSERT(out);
14097  if (!out || !style)
14098  return nk_false;
14099 
14100  /* calculate button content space */
14101  content->x = r.x + style->padding.x + style->border + style->rounding;
14102  content->y = r.y + style->padding.y + style->border + style->rounding;
14103  content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
14104  content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
14105 
14106  /* execute button behavior */
14107  bounds.x = r.x - style->touch_padding.x;
14108  bounds.y = r.y - style->touch_padding.y;
14109  bounds.w = r.w + 2 * style->touch_padding.x;
14110  bounds.h = r.h + 2 * style->touch_padding.y;
14111  return nk_button_behavior(state, bounds, in, behavior);
14112 }
14113 
14114 NK_INTERN void
14115 nk_draw_button_text(struct nk_command_buffer *out,
14116  const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
14117  const struct nk_style_button *style, const char *txt, int len,
14118  nk_flags text_alignment, const struct nk_user_font *font)
14119 {
14120  struct nk_text text;
14121  const struct nk_style_item *background;
14122  background = nk_draw_button(out, bounds, state, style);
14123 
14124  /* select correct colors/images */
14125  if (background->type == NK_STYLE_ITEM_COLOR)
14126  text.background = background->data.color;
14127  else text.background = style->text_background;
14128  if (state & NK_WIDGET_STATE_HOVER)
14129  text.text = style->text_hover;
14130  else if (state & NK_WIDGET_STATE_ACTIVED)
14131  text.text = style->text_active;
14132  else text.text = style->text_normal;
14133 
14134  text.padding = nk_vec2(0,0);
14135  nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
14136 }
14137 
14138 NK_INTERN int
14139 nk_do_button_text(nk_flags *state,
14140  struct nk_command_buffer *out, struct nk_rect bounds,
14141  const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
14142  const struct nk_style_button *style, const struct nk_input *in,
14143  const struct nk_user_font *font)
14144 {
14145  struct nk_rect content;
14146  int ret = nk_false;
14147 
14148  NK_ASSERT(state);
14149  NK_ASSERT(style);
14150  NK_ASSERT(out);
14151  NK_ASSERT(string);
14152  NK_ASSERT(font);
14153  if (!out || !style || !font || !string)
14154  return nk_false;
14155 
14156  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14157  if (style->draw_begin) style->draw_begin(out, style->userdata);
14158  nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
14159  if (style->draw_end) style->draw_end(out, style->userdata);
14160  return ret;
14161 }
14162 
14163 NK_INTERN void
14164 nk_draw_button_symbol(struct nk_command_buffer *out,
14165  const struct nk_rect *bounds, const struct nk_rect *content,
14166  nk_flags state, const struct nk_style_button *style,
14167  enum nk_symbol_type type, const struct nk_user_font *font)
14168 {
14169  struct nk_color sym, bg;
14170  const struct nk_style_item *background;
14171 
14172  /* select correct colors/images */
14173  background = nk_draw_button(out, bounds, state, style);
14174  if (background->type == NK_STYLE_ITEM_COLOR)
14175  bg = background->data.color;
14176  else bg = style->text_background;
14177 
14178  if (state & NK_WIDGET_STATE_HOVER)
14179  sym = style->text_hover;
14180  else if (state & NK_WIDGET_STATE_ACTIVED)
14181  sym = style->text_active;
14182  else sym = style->text_normal;
14183  nk_draw_symbol(out, type, *content, bg, sym, 1, font);
14184 }
14185 
14186 NK_INTERN int
14187 nk_do_button_symbol(nk_flags *state,
14188  struct nk_command_buffer *out, struct nk_rect bounds,
14189  enum nk_symbol_type symbol, enum nk_button_behavior behavior,
14190  const struct nk_style_button *style, const struct nk_input *in,
14191  const struct nk_user_font *font)
14192 {
14193  int ret;
14194  struct nk_rect content;
14195 
14196  NK_ASSERT(state);
14197  NK_ASSERT(style);
14198  NK_ASSERT(font);
14199  NK_ASSERT(out);
14200  if (!out || !style || !font || !state)
14201  return nk_false;
14202 
14203  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14204  if (style->draw_begin) style->draw_begin(out, style->userdata);
14205  nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
14206  if (style->draw_end) style->draw_end(out, style->userdata);
14207  return ret;
14208 }
14209 
14210 NK_INTERN void
14211 nk_draw_button_image(struct nk_command_buffer *out,
14212  const struct nk_rect *bounds, const struct nk_rect *content,
14213  nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
14214 {
14215  nk_draw_button(out, bounds, state, style);
14216  nk_draw_image(out, *content, img, nk_white);
14217 }
14218 
14219 NK_INTERN int
14220 nk_do_button_image(nk_flags *state,
14221  struct nk_command_buffer *out, struct nk_rect bounds,
14222  struct nk_image img, enum nk_button_behavior b,
14223  const struct nk_style_button *style, const struct nk_input *in)
14224 {
14225  int ret;
14226  struct nk_rect content;
14227 
14228  NK_ASSERT(state);
14229  NK_ASSERT(style);
14230  NK_ASSERT(out);
14231  if (!out || !style || !state)
14232  return nk_false;
14233 
14234  ret = nk_do_button(state, out, bounds, style, in, b, &content);
14235  content.x += style->image_padding.x;
14236  content.y += style->image_padding.y;
14237  content.w -= 2 * style->image_padding.x;
14238  content.h -= 2 * style->image_padding.y;
14239 
14240  if (style->draw_begin) style->draw_begin(out, style->userdata);
14241  nk_draw_button_image(out, &bounds, &content, *state, style, &img);
14242  if (style->draw_end) style->draw_end(out, style->userdata);
14243  return ret;
14244 }
14245 
14246 NK_INTERN void
14247 nk_draw_button_text_symbol(struct nk_command_buffer *out,
14248  const struct nk_rect *bounds, const struct nk_rect *label,
14249  const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
14250  const char *str, int len, enum nk_symbol_type type,
14251  const struct nk_user_font *font)
14252 {
14253  struct nk_color sym;
14254  struct nk_text text;
14255  const struct nk_style_item *background;
14256 
14257  /* select correct background colors/images */
14258  background = nk_draw_button(out, bounds, state, style);
14259  if (background->type == NK_STYLE_ITEM_COLOR)
14260  text.background = background->data.color;
14261  else text.background = style->text_background;
14262 
14263  /* select correct text colors */
14264  if (state & NK_WIDGET_STATE_HOVER) {
14265  sym = style->text_hover;
14266  text.text = style->text_hover;
14267  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14268  sym = style->text_active;
14269  text.text = style->text_active;
14270  } else {
14271  sym = style->text_normal;
14272  text.text = style->text_normal;
14273  }
14274 
14275  text.padding = nk_vec2(0,0);
14276  nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
14277  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14278 }
14279 
14280 NK_INTERN int
14281 nk_do_button_text_symbol(nk_flags *state,
14282  struct nk_command_buffer *out, struct nk_rect bounds,
14283  enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
14284  enum nk_button_behavior behavior, const struct nk_style_button *style,
14285  const struct nk_user_font *font, const struct nk_input *in)
14286 {
14287  int ret;
14288  struct nk_rect tri = {0,0,0,0};
14289  struct nk_rect content;
14290 
14291  NK_ASSERT(style);
14292  NK_ASSERT(out);
14293  NK_ASSERT(font);
14294  if (!out || !style || !font)
14295  return nk_false;
14296 
14297  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14298  tri.y = content.y + (content.h/2) - font->height/2;
14299  tri.w = font->height; tri.h = font->height;
14300  if (align & NK_TEXT_ALIGN_LEFT) {
14301  tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
14302  tri.x = NK_MAX(tri.x, 0);
14303  } else tri.x = content.x + 2 * style->padding.x;
14304 
14305  /* draw button */
14306  if (style->draw_begin) style->draw_begin(out, style->userdata);
14307  nk_draw_button_text_symbol(out, &bounds, &content, &tri,
14308  *state, style, str, len, symbol, font);
14309  if (style->draw_end) style->draw_end(out, style->userdata);
14310  return ret;
14311 }
14312 
14313 NK_INTERN void
14314 nk_draw_button_text_image(struct nk_command_buffer *out,
14315  const struct nk_rect *bounds, const struct nk_rect *label,
14316  const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
14317  const char *str, int len, const struct nk_user_font *font,
14318  const struct nk_image *img)
14319 {
14320  struct nk_text text;
14321  const struct nk_style_item *background;
14322  background = nk_draw_button(out, bounds, state, style);
14323 
14324  /* select correct colors */
14325  if (background->type == NK_STYLE_ITEM_COLOR)
14326  text.background = background->data.color;
14327  else text.background = style->text_background;
14328  if (state & NK_WIDGET_STATE_HOVER)
14329  text.text = style->text_hover;
14330  else if (state & NK_WIDGET_STATE_ACTIVED)
14331  text.text = style->text_active;
14332  else text.text = style->text_normal;
14333 
14334  text.padding = nk_vec2(0,0);
14335  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14336  nk_draw_image(out, *image, img, nk_white);
14337 }
14338 
14339 NK_INTERN int
14340 nk_do_button_text_image(nk_flags *state,
14341  struct nk_command_buffer *out, struct nk_rect bounds,
14342  struct nk_image img, const char* str, int len, nk_flags align,
14343  enum nk_button_behavior behavior, const struct nk_style_button *style,
14344  const struct nk_user_font *font, const struct nk_input *in)
14345 {
14346  int ret;
14347  struct nk_rect icon;
14348  struct nk_rect content;
14349 
14350  NK_ASSERT(style);
14351  NK_ASSERT(state);
14352  NK_ASSERT(font);
14353  NK_ASSERT(out);
14354  if (!out || !font || !style || !str)
14355  return nk_false;
14356 
14357  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14358  icon.y = bounds.y + style->padding.y;
14359  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14360  if (align & NK_TEXT_ALIGN_LEFT) {
14361  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14362  icon.x = NK_MAX(icon.x, 0);
14363  } else icon.x = bounds.x + 2 * style->padding.x;
14364 
14365  icon.x += style->image_padding.x;
14366  icon.y += style->image_padding.y;
14367  icon.w -= 2 * style->image_padding.x;
14368  icon.h -= 2 * style->image_padding.y;
14369 
14370  if (style->draw_begin) style->draw_begin(out, style->userdata);
14371  nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
14372  if (style->draw_end) style->draw_end(out, style->userdata);
14373  return ret;
14374 }
14375 
14376 /* ===============================================================
14377  *
14378  * TOGGLE
14379  *
14380  * ===============================================================*/
14381 enum nk_toggle_type {
14382  NK_TOGGLE_CHECK,
14383  NK_TOGGLE_OPTION
14384 };
14385 
14386 NK_INTERN int
14387 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
14388  nk_flags *state, int active)
14389 {
14390  nk_widget_state_reset(state);
14391  if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) {
14392  *state = NK_WIDGET_STATE_ACTIVE;
14393  active = !active;
14394  }
14395  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select))
14396  *state |= NK_WIDGET_STATE_ENTERED;
14397  else if (nk_input_is_mouse_prev_hovering_rect(in, select))
14398  *state |= NK_WIDGET_STATE_LEFT;
14399  return active;
14400 }
14401 
14402 NK_INTERN void
14403 nk_draw_checkbox(struct nk_command_buffer *out,
14404  nk_flags state, const struct nk_style_toggle *style, int active,
14405  const struct nk_rect *label, const struct nk_rect *selector,
14406  const struct nk_rect *cursors, const char *string, int len,
14407  const struct nk_user_font *font)
14408 {
14409  const struct nk_style_item *background;
14410  const struct nk_style_item *cursor;
14411  struct nk_text text;
14412 
14413  /* select correct colors/images */
14414  if (state & NK_WIDGET_STATE_HOVER) {
14415  background = &style->hover;
14416  cursor = &style->cursor_hover;
14417  text.text = style->text_hover;
14418  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14419  background = &style->hover;
14420  cursor = &style->cursor_hover;
14421  text.text = style->text_active;
14422  } else {
14423  background = &style->normal;
14424  cursor = &style->cursor_normal;
14425  text.text = style->text_normal;
14426  }
14427 
14428  /* draw background and cursor */
14429  if (background->type == NK_STYLE_ITEM_COLOR) {
14430  nk_fill_rect(out, *selector, 0, style->border_color);
14431  nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
14432  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14433  if (active) {
14434  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14435  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14436  else nk_fill_rect(out, *cursors, 0, cursor->data.color);
14437  }
14438 
14439  text.padding.x = 0;
14440  text.padding.y = 0;
14441  text.background = style->text_background;
14442  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14443 }
14444 
14445 NK_INTERN void
14446 nk_draw_option(struct nk_command_buffer *out,
14447  nk_flags state, const struct nk_style_toggle *style, int active,
14448  const struct nk_rect *label, const struct nk_rect *selector,
14449  const struct nk_rect *cursors, const char *string, int len,
14450  const struct nk_user_font *font)
14451 {
14452  const struct nk_style_item *background;
14453  const struct nk_style_item *cursor;
14454  struct nk_text text;
14455 
14456  /* select correct colors/images */
14457  if (state & NK_WIDGET_STATE_HOVER) {
14458  background = &style->hover;
14459  cursor = &style->cursor_hover;
14460  text.text = style->text_hover;
14461  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14462  background = &style->hover;
14463  cursor = &style->cursor_hover;
14464  text.text = style->text_active;
14465  } else {
14466  background = &style->normal;
14467  cursor = &style->cursor_normal;
14468  text.text = style->text_normal;
14469  }
14470 
14471  /* draw background and cursor */
14472  if (background->type == NK_STYLE_ITEM_COLOR) {
14473  nk_fill_circle(out, *selector, style->border_color);
14474  nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
14475  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14476  if (active) {
14477  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14478  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14479  else nk_fill_circle(out, *cursors, cursor->data.color);
14480  }
14481 
14482  text.padding.x = 0;
14483  text.padding.y = 0;
14484  text.background = style->text_background;
14485  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14486 }
14487 
14488 NK_INTERN int
14489 nk_do_toggle(nk_flags *state,
14490  struct nk_command_buffer *out, struct nk_rect r,
14491  int *active, const char *str, int len, enum nk_toggle_type type,
14492  const struct nk_style_toggle *style, const struct nk_input *in,
14493  const struct nk_user_font *font)
14494 {
14495  int was_active;
14496  struct nk_rect bounds;
14497  struct nk_rect select;
14498  struct nk_rect cursor;
14499  struct nk_rect label;
14500 
14501  NK_ASSERT(style);
14502  NK_ASSERT(out);
14503  NK_ASSERT(font);
14504  if (!out || !style || !font || !active)
14505  return 0;
14506 
14507  r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
14508  r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
14509 
14510  /* add additional touch padding for touch screen devices */
14511  bounds.x = r.x - style->touch_padding.x;
14512  bounds.y = r.y - style->touch_padding.y;
14513  bounds.w = r.w + 2 * style->touch_padding.x;
14514  bounds.h = r.h + 2 * style->touch_padding.y;
14515 
14516  /* calculate the selector space */
14517  select.w = font->height;
14518  select.h = select.w;
14519  select.y = r.y + r.h/2.0f - select.h/2.0f;
14520  select.x = r.x;
14521 
14522  /* calculate the bounds of the cursor inside the selector */
14523  cursor.x = select.x + style->padding.x + style->border;
14524  cursor.y = select.y + style->padding.y + style->border;
14525  cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
14526  cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
14527 
14528  /* label behind the selector */
14529  label.x = select.x + select.w + style->spacing;
14530  label.y = select.y;
14531  label.w = NK_MAX(r.x + r.w, label.x) - label.x;
14532  label.h = select.w;
14533 
14534  /* update selector */
14535  was_active = *active;
14536  *active = nk_toggle_behavior(in, bounds, state, *active);
14537 
14538  /* draw selector */
14539  if (style->draw_begin)
14540  style->draw_begin(out, style->userdata);
14541  if (type == NK_TOGGLE_CHECK) {
14542  nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14543  } else {
14544  nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14545  }
14546  if (style->draw_end)
14547  style->draw_end(out, style->userdata);
14548  return (was_active != *active);
14549 }
14550 
14551 /* ===============================================================
14552  *
14553  * SELECTABLE
14554  *
14555  * ===============================================================*/
14556 NK_INTERN void
14557 nk_draw_selectable(struct nk_command_buffer *out,
14558  nk_flags state, const struct nk_style_selectable *style, int active,
14559  const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img,
14560  const char *string, int len, nk_flags align, const struct nk_user_font *font)
14561 {
14562  const struct nk_style_item *background;
14563  struct nk_text text;
14564  text.padding = style->padding;
14565 
14566  /* select correct colors/images */
14567  if (!active) {
14568  if (state & NK_WIDGET_STATE_ACTIVED) {
14569  background = &style->pressed;
14570  text.text = style->text_pressed;
14571  } else if (state & NK_WIDGET_STATE_HOVER) {
14572  background = &style->hover;
14573  text.text = style->text_hover;
14574  } else {
14575  background = &style->normal;
14576  text.text = style->text_normal;
14577  }
14578  } else {
14579  if (state & NK_WIDGET_STATE_ACTIVED) {
14580  background = &style->pressed_active;
14581  text.text = style->text_pressed_active;
14582  } else if (state & NK_WIDGET_STATE_HOVER) {
14583  background = &style->hover_active;
14584  text.text = style->text_hover_active;
14585  } else {
14586  background = &style->normal_active;
14587  text.text = style->text_normal_active;
14588  }
14589  }
14590 
14591 
14592  /* draw selectable background and text */
14593  if (background->type == NK_STYLE_ITEM_IMAGE) {
14594  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14595  text.background = nk_rgba(0,0,0,0);
14596  } else {
14597  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14598  text.background = background->data.color;
14599  }
14600  if (img && icon) nk_draw_image(out, *icon, img, nk_white);
14601  nk_widget_text(out, *bounds, string, len, &text, align, font);
14602 }
14603 
14604 NK_INTERN int
14605 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
14606  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14607  const struct nk_style_selectable *style, const struct nk_input *in,
14608  const struct nk_user_font *font)
14609 {
14610  int old_value;
14611  struct nk_rect touch;
14612 
14613  NK_ASSERT(state);
14614  NK_ASSERT(out);
14615  NK_ASSERT(str);
14616  NK_ASSERT(len);
14617  NK_ASSERT(value);
14618  NK_ASSERT(style);
14619  NK_ASSERT(font);
14620 
14621  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14622  old_value = *value;
14623 
14624  /* remove padding */
14625  touch.x = bounds.x - style->touch_padding.x;
14626  touch.y = bounds.y - style->touch_padding.y;
14627  touch.w = bounds.w + style->touch_padding.x * 2;
14628  touch.h = bounds.h + style->touch_padding.y * 2;
14629 
14630  /* update button */
14631  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14632  *value = !(*value);
14633 
14634  /* draw selectable */
14635  if (style->draw_begin) style->draw_begin(out, style->userdata);
14636  nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font);
14637  if (style->draw_end) style->draw_end(out, style->userdata);
14638  return old_value != *value;
14639 }
14640 
14641 NK_INTERN int
14642 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
14643  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14644  const struct nk_image *img, const struct nk_style_selectable *style,
14645  const struct nk_input *in, const struct nk_user_font *font)
14646 {
14647  int old_value;
14648  struct nk_rect touch;
14649  struct nk_rect icon;
14650 
14651  NK_ASSERT(state);
14652  NK_ASSERT(out);
14653  NK_ASSERT(str);
14654  NK_ASSERT(len);
14655  NK_ASSERT(value);
14656  NK_ASSERT(style);
14657  NK_ASSERT(font);
14658 
14659  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14660  old_value = *value;
14661 
14662  /* toggle behavior */
14663  touch.x = bounds.x - style->touch_padding.x;
14664  touch.y = bounds.y - style->touch_padding.y;
14665  touch.w = bounds.w + style->touch_padding.x * 2;
14666  touch.h = bounds.h + style->touch_padding.y * 2;
14667  if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT))
14668  *value = !(*value);
14669 
14670  icon.y = bounds.y + style->padding.y;
14671  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14672  if (align & NK_TEXT_ALIGN_LEFT) {
14673  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14674  icon.x = NK_MAX(icon.x, 0);
14675  } else icon.x = bounds.x + 2 * style->padding.x;
14676 
14677  icon.x += style->image_padding.x;
14678  icon.y += style->image_padding.y;
14679  icon.w -= 2 * style->image_padding.x;
14680  icon.h -= 2 * style->image_padding.y;
14681 
14682  /* draw selectable */
14683  if (style->draw_begin) style->draw_begin(out, style->userdata);
14684  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font);
14685  if (style->draw_end) style->draw_end(out, style->userdata);
14686  return old_value != *value;
14687 }
14688 
14689 
14690 /* ===============================================================
14691  *
14692  * SLIDER
14693  *
14694  * ===============================================================*/
14695 NK_INTERN float
14696 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
14697  struct nk_rect *visual_cursor, struct nk_input *in,
14698  struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
14699  float slider_step, float slider_steps)
14700 {
14701  int left_mouse_down;
14702  int left_mouse_click_in_cursor;
14703 
14704  /* check if visual cursor is being dragged */
14705  nk_widget_state_reset(state);
14706  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
14707  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
14708  NK_BUTTON_LEFT, *visual_cursor, nk_true);
14709 
14710  if (left_mouse_down && left_mouse_click_in_cursor)
14711  {
14712  float ratio = 0;
14713  const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
14714  const float pxstep = bounds.w / slider_steps;
14715 
14716  /* only update value if the next slider step is reached */
14717  *state = NK_WIDGET_STATE_ACTIVE;
14718  if (NK_ABS(d) >= pxstep) {
14719  const float steps = (float)((int)(NK_ABS(d) / pxstep));
14720  slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
14721  slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
14722  ratio = (slider_value - slider_min)/slider_step;
14723  logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
14724  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
14725  }
14726  }
14727 
14728  /* slider widget state */
14729  if (nk_input_is_mouse_hovering_rect(in, bounds))
14730  *state = NK_WIDGET_STATE_HOVERED;
14731  if (*state & NK_WIDGET_STATE_HOVER &&
14733  *state |= NK_WIDGET_STATE_ENTERED;
14734  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
14735  *state |= NK_WIDGET_STATE_LEFT;
14736  return slider_value;
14737 }
14738 
14739 NK_INTERN void
14740 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
14741  const struct nk_style_slider *style, const struct nk_rect *bounds,
14742  const struct nk_rect *visual_cursor, float min, float value, float max)
14743 {
14744  struct nk_rect fill;
14745  struct nk_rect bar;
14746  const struct nk_style_item *background;
14747 
14748  /* select correct slider images/colors */
14749  struct nk_color bar_color;
14750  const struct nk_style_item *cursor;
14751 
14752  NK_UNUSED(min);
14753  NK_UNUSED(max);
14754  NK_UNUSED(value);
14755 
14756  if (state & NK_WIDGET_STATE_ACTIVED) {
14757  background = &style->active;
14758  bar_color = style->bar_active;
14759  cursor = &style->cursor_active;
14760  } else if (state & NK_WIDGET_STATE_HOVER) {
14761  background = &style->hover;
14762  bar_color = style->bar_hover;
14763  cursor = &style->cursor_hover;
14764  } else {
14765  background = &style->normal;
14766  bar_color = style->bar_normal;
14767  cursor = &style->cursor_normal;
14768  }
14769 
14770  /* calculate slider background bar */
14771  bar.x = bounds->x;
14772  bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
14773  bar.w = bounds->w;
14774  bar.h = bounds->h/6;
14775 
14776  /* filled background bar style */
14777  fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
14778  fill.x = bar.x;
14779  fill.y = bar.y;
14780  fill.h = bar.h;
14781 
14782  /* draw background */
14783  if (background->type == NK_STYLE_ITEM_IMAGE) {
14784  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14785  } else {
14786  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14787  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14788  }
14789 
14790  /* draw slider bar */
14791  nk_fill_rect(out, bar, style->rounding, bar_color);
14792  nk_fill_rect(out, fill, style->rounding, style->bar_filled);
14793 
14794  /* draw cursor */
14795  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14796  nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
14797  else nk_fill_circle(out, *visual_cursor, cursor->data.color);
14798 }
14799 
14800 NK_INTERN float
14801 nk_do_slider(nk_flags *state,
14802  struct nk_command_buffer *out, struct nk_rect bounds,
14803  float min, float val, float max, float step,
14804  const struct nk_style_slider *style, struct nk_input *in,
14805  const struct nk_user_font *font)
14806 {
14807  float slider_range;
14808  float slider_min;
14809  float slider_max;
14810  float slider_value;
14811  float slider_steps;
14812  float cursor_offset;
14813 
14814  struct nk_rect visual_cursor;
14815  struct nk_rect logical_cursor;
14816 
14817  NK_ASSERT(style);
14818  NK_ASSERT(out);
14819  if (!out || !style)
14820  return 0;
14821 
14822  /* remove padding from slider bounds */
14823  bounds.x = bounds.x + style->padding.x;
14824  bounds.y = bounds.y + style->padding.y;
14825  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
14826  bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
14827  bounds.w -= 2 * style->padding.x;
14828  bounds.h -= 2 * style->padding.y;
14829 
14830  /* optional buttons */
14831  if (style->show_buttons) {
14832  nk_flags ws;
14833  struct nk_rect button;
14834  button.y = bounds.y;
14835  button.w = bounds.h;
14836  button.h = bounds.h;
14837 
14838  /* decrement button */
14839  button.x = bounds.x;
14840  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
14841  &style->dec_button, in, font))
14842  val -= step;
14843 
14844  /* increment button */
14845  button.x = (bounds.x + bounds.w) - button.w;
14846  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
14847  &style->inc_button, in, font))
14848  val += step;
14849 
14850  bounds.x = bounds.x + button.w + style->spacing.x;
14851  bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
14852  }
14853 
14854  /* remove one cursor size to support visual cursor */
14855  bounds.x += style->cursor_size.x*0.5f;
14856  bounds.w -= style->cursor_size.x;
14857 
14858  /* make sure the provided values are correct */
14859  slider_max = NK_MAX(min, max);
14860  slider_min = NK_MIN(min, max);
14861  slider_value = NK_CLAMP(slider_min, val, slider_max);
14862  slider_range = slider_max - slider_min;
14863  slider_steps = slider_range / step;
14864  cursor_offset = (slider_value - slider_min) / step;
14865 
14866  /* calculate cursor
14867  Basically you have two cursors. One for visual representation and interaction
14868  and one for updating the actual cursor value. */
14869  logical_cursor.h = bounds.h;
14870  logical_cursor.w = bounds.w / slider_steps;
14871  logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
14872  logical_cursor.y = bounds.y;
14873 
14874  visual_cursor.h = style->cursor_size.y;
14875  visual_cursor.w = style->cursor_size.x;
14876  visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
14877  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14878 
14879  slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
14880  in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
14881  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14882 
14883  /* draw slider */
14884  if (style->draw_begin) style->draw_begin(out, style->userdata);
14885  nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
14886  if (style->draw_end) style->draw_end(out, style->userdata);
14887  return slider_value;
14888 }
14889 
14890 /* ===============================================================
14891  *
14892  * PROGRESSBAR
14893  *
14894  * ===============================================================*/
14895 NK_INTERN nk_size
14896 nk_progress_behavior(nk_flags *state, const struct nk_input *in,
14897  struct nk_rect r, nk_size max, nk_size value, int modifiable)
14898 {
14899  nk_widget_state_reset(state);
14900  if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) {
14901  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14902  int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14903  NK_BUTTON_LEFT, r, nk_true);
14904 
14905  if (left_mouse_down && left_mouse_click_in_cursor) {
14906  float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w;
14907  value = (nk_size)NK_MAX(0,((float)max * ratio));
14908  *state = NK_WIDGET_STATE_ACTIVE;
14909  } else *state = NK_WIDGET_STATE_HOVERED;
14910  }
14911 
14912  /* set progressbar widget state */
14913  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r))
14914  *state |= NK_WIDGET_STATE_ENTERED;
14915  else if (nk_input_is_mouse_prev_hovering_rect(in, r))
14916  *state |= NK_WIDGET_STATE_LEFT;
14917 
14918  if (!max) return value;
14919  value = NK_MIN(value, max);
14920  return value;
14921 }
14922 
14923 NK_INTERN void
14924 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
14925  const struct nk_style_progress *style, const struct nk_rect *bounds,
14926  const struct nk_rect *scursor, nk_size value, nk_size max)
14927 {
14928  const struct nk_style_item *background;
14929  const struct nk_style_item *cursor;
14930 
14931  NK_UNUSED(max);
14932  NK_UNUSED(value);
14933 
14934  /* select correct colors/images to draw */
14935  if (state & NK_WIDGET_STATE_ACTIVED) {
14936  background = &style->active;
14937  cursor = &style->cursor_active;
14938  } else if (state & NK_WIDGET_STATE_HOVER){
14939  background = &style->hover;
14940  cursor = &style->cursor_hover;
14941  } else {
14942  background = &style->normal;
14943  cursor = &style->cursor_normal;
14944  }
14945 
14946  /* draw background */
14947  if (background->type == NK_STYLE_ITEM_COLOR) {
14948  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14949  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14950  } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
14951 
14952  /* draw cursor */
14953  if (background->type == NK_STYLE_ITEM_COLOR) {
14954  nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
14955  nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
14956  } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
14957 }
14958 
14959 NK_INTERN nk_size
14960 nk_do_progress(nk_flags *state,
14961  struct nk_command_buffer *out, struct nk_rect bounds,
14962  nk_size value, nk_size max, int modifiable,
14963  const struct nk_style_progress *style, const struct nk_input *in)
14964 {
14965  float prog_scale;
14966  nk_size prog_value;
14967  struct nk_rect cursor;
14968 
14969  NK_ASSERT(style);
14970  NK_ASSERT(out);
14971  if (!out || !style) return 0;
14972 
14973  /* calculate progressbar cursor */
14974  cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
14975  cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
14976  cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
14977  prog_scale = (float)value / (float)max;
14978  cursor.w = (bounds.w - 2) * prog_scale;
14979 
14980  /* update progressbar */
14981  prog_value = NK_MIN(value, max);
14982  prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable);
14983 
14984  /* draw progressbar */
14985  if (style->draw_begin) style->draw_begin(out, style->userdata);
14986  nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
14987  if (style->draw_end) style->draw_end(out, style->userdata);
14988  return prog_value;
14989 }
14990 
14991 /* ===============================================================
14992  *
14993  * SCROLLBAR
14994  *
14995  * ===============================================================*/
14996 NK_INTERN float
14997 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
14998  int has_scrolling, const struct nk_rect *scroll,
14999  const struct nk_rect *cursor, const struct nk_rect *empty0,
15000  const struct nk_rect *empty1, float scroll_offset,
15001  float target, float scroll_step, enum nk_orientation o)
15002 {
15003  nk_flags ws = 0;
15004  int left_mouse_down;
15005  int left_mouse_click_in_cursor;
15006  float scroll_delta;
15007 
15008  nk_widget_state_reset(state);
15009  if (!in) return scroll_offset;
15010 
15011  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15012  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
15013  NK_BUTTON_LEFT, *cursor, nk_true);
15014  if (nk_input_is_mouse_hovering_rect(in, *scroll))
15015  *state = NK_WIDGET_STATE_HOVERED;
15016 
15017  scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
15018  if (left_mouse_down && left_mouse_click_in_cursor) {
15019  /* update cursor by mouse dragging */
15020  float pixel, delta;
15021  *state = NK_WIDGET_STATE_ACTIVE;
15022  if (o == NK_VERTICAL) {
15023  float cursor_y;
15024  pixel = in->mouse.delta.y;
15025  delta = (pixel / scroll->h) * target;
15026  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
15027  cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
15028  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
15029  } else {
15030  float cursor_x;
15031  pixel = in->mouse.delta.x;
15032  delta = (pixel / scroll->w) * target;
15033  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
15034  cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
15035  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
15036  }
15037  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
15038  nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
15039  /* scroll page up by click on empty space or shortcut */
15040  if (o == NK_VERTICAL)
15041  scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
15042  else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
15043  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
15044  nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
15045  /* scroll page down by click on empty space or shortcut */
15046  if (o == NK_VERTICAL)
15047  scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
15048  else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
15049  } else if (has_scrolling) {
15050  if ((scroll_delta < 0 || (scroll_delta > 0))) {
15051  /* update cursor by mouse scrolling */
15052  scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
15053  if (o == NK_VERTICAL)
15054  scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
15055  else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
15056  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) {
15057  /* update cursor to the beginning */
15058  if (o == NK_VERTICAL) scroll_offset = 0;
15059  } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) {
15060  /* update cursor to the end */
15061  if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
15062  }
15063  }
15064  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll))
15065  *state |= NK_WIDGET_STATE_ENTERED;
15066  else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
15067  *state |= NK_WIDGET_STATE_LEFT;
15068  return scroll_offset;
15069 }
15070 
15071 NK_INTERN void
15072 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
15073  const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
15074  const struct nk_rect *scroll)
15075 {
15076  const struct nk_style_item *background;
15077  const struct nk_style_item *cursor;
15078 
15079  /* select correct colors/images to draw */
15080  if (state & NK_WIDGET_STATE_ACTIVED) {
15081  background = &style->active;
15082  cursor = &style->cursor_active;
15083  } else if (state & NK_WIDGET_STATE_HOVER) {
15084  background = &style->hover;
15085  cursor = &style->cursor_hover;
15086  } else {
15087  background = &style->normal;
15088  cursor = &style->cursor_normal;
15089  }
15090 
15091  /* draw background */
15092  if (background->type == NK_STYLE_ITEM_COLOR) {
15093  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
15094  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
15095  } else {
15096  nk_draw_image(out, *bounds, &background->data.image, nk_white);
15097  }
15098 
15099  /* draw cursor */
15100  if (background->type == NK_STYLE_ITEM_COLOR) {
15101  nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
15102  nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
15103  } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
15104 }
15105 
15106 NK_INTERN float
15107 nk_do_scrollbarv(nk_flags *state,
15108  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15109  float offset, float target, float step, float button_pixel_inc,
15110  const struct nk_style_scrollbar *style, struct nk_input *in,
15111  const struct nk_user_font *font)
15112 {
15113  struct nk_rect empty_north;
15114  struct nk_rect empty_south;
15115  struct nk_rect cursor;
15116 
15117  float scroll_step;
15118  float scroll_offset;
15119  float scroll_off;
15120  float scroll_ratio;
15121 
15122  NK_ASSERT(out);
15123  NK_ASSERT(style);
15124  NK_ASSERT(state);
15125  if (!out || !style) return 0;
15126 
15127  scroll.w = NK_MAX(scroll.w, 1);
15128  scroll.h = NK_MAX(scroll.h, 0);
15129  if (target <= scroll.h) return 0;
15130 
15131  /* optional scrollbar buttons */
15132  if (style->show_buttons) {
15133  nk_flags ws;
15134  float scroll_h;
15135  struct nk_rect button;
15136 
15137  button.x = scroll.x;
15138  button.w = scroll.w;
15139  button.h = scroll.w;
15140 
15141  scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
15142  scroll_step = NK_MIN(step, button_pixel_inc);
15143 
15144  /* decrement button */
15145  button.y = scroll.y;
15146  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15147  NK_BUTTON_REPEATER, &style->dec_button, in, font))
15148  offset = offset - scroll_step;
15149 
15150  /* increment button */
15151  button.y = scroll.y + scroll.h - button.h;
15152  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15153  NK_BUTTON_REPEATER, &style->inc_button, in, font))
15154  offset = offset + scroll_step;
15155 
15156  scroll.y = scroll.y + button.h;
15157  scroll.h = scroll_h;
15158  }
15159 
15160  /* calculate scrollbar constants */
15161  scroll_step = NK_MIN(step, scroll.h);
15162  scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
15163  scroll_ratio = scroll.h / target;
15164  scroll_off = scroll_offset / target;
15165 
15166  /* calculate scrollbar cursor bounds */
15167  cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
15168  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
15169  cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
15170  cursor.x = scroll.x + style->border + style->padding.x;
15171 
15172  /* calculate empty space around cursor */
15173  empty_north.x = scroll.x;
15174  empty_north.y = scroll.y;
15175  empty_north.w = scroll.w;
15176  empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
15177 
15178  empty_south.x = scroll.x;
15179  empty_south.y = cursor.y + cursor.h;
15180  empty_south.w = scroll.w;
15181  empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
15182 
15183  /* update scrollbar */
15184  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15185  &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
15186  scroll_off = scroll_offset / target;
15187  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
15188 
15189  /* draw scrollbar */
15190  if (style->draw_begin) style->draw_begin(out, style->userdata);
15191  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15192  if (style->draw_end) style->draw_end(out, style->userdata);
15193  return scroll_offset;
15194 }
15195 
15196 NK_INTERN float
15197 nk_do_scrollbarh(nk_flags *state,
15198  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15199  float offset, float target, float step, float button_pixel_inc,
15200  const struct nk_style_scrollbar *style, struct nk_input *in,
15201  const struct nk_user_font *font)
15202 {
15203  struct nk_rect cursor;
15204  struct nk_rect empty_west;
15205  struct nk_rect empty_east;
15206 
15207  float scroll_step;
15208  float scroll_offset;
15209  float scroll_off;
15210  float scroll_ratio;
15211 
15212  NK_ASSERT(out);
15213  NK_ASSERT(style);
15214  if (!out || !style) return 0;
15215 
15216  /* scrollbar background */
15217  scroll.h = NK_MAX(scroll.h, 1);
15218  scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
15219  if (target <= scroll.w) return 0;
15220 
15221  /* optional scrollbar buttons */
15222  if (style->show_buttons) {
15223  nk_flags ws;
15224  float scroll_w;
15225  struct nk_rect button;
15226  button.y = scroll.y;
15227  button.w = scroll.h;
15228  button.h = scroll.h;
15229 
15230  scroll_w = scroll.w - 2 * button.w;
15231  scroll_step = NK_MIN(step, button_pixel_inc);
15232 
15233  /* decrement button */
15234  button.x = scroll.x;
15235  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15236  NK_BUTTON_REPEATER, &style->dec_button, in, font))
15237  offset = offset - scroll_step;
15238 
15239  /* increment button */
15240  button.x = scroll.x + scroll.w - button.w;
15241  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15242  NK_BUTTON_REPEATER, &style->inc_button, in, font))
15243  offset = offset + scroll_step;
15244 
15245  scroll.x = scroll.x + button.w;
15246  scroll.w = scroll_w;
15247  }
15248 
15249  /* calculate scrollbar constants */
15250  scroll_step = NK_MIN(step, scroll.w);
15251  scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
15252  scroll_ratio = scroll.w / target;
15253  scroll_off = scroll_offset / target;
15254 
15255  /* calculate cursor bounds */
15256  cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
15257  cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
15258  cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
15259  cursor.y = scroll.y + style->border + style->padding.y;
15260 
15261  /* calculate empty space around cursor */
15262  empty_west.x = scroll.x;
15263  empty_west.y = scroll.y;
15264  empty_west.w = cursor.x - scroll.x;
15265  empty_west.h = scroll.h;
15266 
15267  empty_east.x = cursor.x + cursor.w;
15268  empty_east.y = scroll.y;
15269  empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
15270  empty_east.h = scroll.h;
15271 
15272  /* update scrollbar */
15273  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15274  &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
15275  scroll_off = scroll_offset / target;
15276  cursor.x = scroll.x + (scroll_off * scroll.w);
15277 
15278  /* draw scrollbar */
15279  if (style->draw_begin) style->draw_begin(out, style->userdata);
15280  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15281  if (style->draw_end) style->draw_end(out, style->userdata);
15282  return scroll_offset;
15283 }
15284 
15285 /* ===============================================================
15286  *
15287  * FILTER
15288  *
15289  * ===============================================================*/
15290 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
15291 {(void)unicode;NK_UNUSED(box);return nk_true;}
15292 
15293 NK_API int
15294 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
15295 {
15296  NK_UNUSED(box);
15297  if (unicode > 128) return nk_false;
15298  else return nk_true;
15299 }
15300 
15301 NK_API int
15302 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
15303 {
15304  NK_UNUSED(box);
15305  if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
15306  return nk_false;
15307  else return nk_true;
15308 }
15309 
15310 NK_API int
15311 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
15312 {
15313  NK_UNUSED(box);
15314  if ((unicode < '0' || unicode > '9') && unicode != '-')
15315  return nk_false;
15316  else return nk_true;
15317 }
15318 
15319 NK_API int
15320 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
15321 {
15322  NK_UNUSED(box);
15323  if ((unicode < '0' || unicode > '9') &&
15324  (unicode < 'a' || unicode > 'f') &&
15325  (unicode < 'A' || unicode > 'F'))
15326  return nk_false;
15327  else return nk_true;
15328 }
15329 
15330 NK_API int
15331 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
15332 {
15333  NK_UNUSED(box);
15334  if (unicode < '0' || unicode > '7')
15335  return nk_false;
15336  else return nk_true;
15337 }
15338 
15339 NK_API int
15340 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
15341 {
15342  NK_UNUSED(box);
15343  if (unicode != '0' && unicode != '1')
15344  return nk_false;
15345  else return nk_true;
15346 }
15347 
15348 /* ===============================================================
15349  *
15350  * EDIT
15351  *
15352  * ===============================================================*/
15353 NK_INTERN void
15354 nk_edit_draw_text(struct nk_command_buffer *out,
15355  const struct nk_style_edit *style, float pos_x, float pos_y,
15356  float x_offset, const char *text, int byte_len, float row_height,
15357  const struct nk_user_font *font, struct nk_color background,
15358  struct nk_color foreground, int is_selected)
15359 {
15360  NK_ASSERT(out);
15361  NK_ASSERT(font);
15362  NK_ASSERT(style);
15363  if (!text || !byte_len || !out || !style) return;
15364 
15365  {int glyph_len = 0;
15366  nk_rune unicode = 0;
15367  int text_len = 0;
15368  float line_width = 0;
15369  float glyph_width;
15370  const char *line = text;
15371  float line_offset = 0;
15372  int line_count = 0;
15373 
15374  struct nk_text txt;
15375  txt.padding = nk_vec2(0,0);
15376  txt.background = background;
15377  txt.text = foreground;
15378 
15379  glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
15380  if (!glyph_len) return;
15381  while ((text_len < byte_len) && glyph_len)
15382  {
15383  if (unicode == '\n') {
15384  /* new line separator so draw previous line */
15385  struct nk_rect label;
15386  label.y = pos_y + line_offset;
15387  label.h = row_height;
15388  label.w = line_width;
15389  label.x = pos_x;
15390  if (!line_count)
15391  label.x += x_offset;
15392 
15393  if (is_selected) /* selection needs to draw different background color */
15394  nk_fill_rect(out, label, 0, background);
15395  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15396  &txt, NK_TEXT_CENTERED, font);
15397 
15398  text_len++;
15399  line_count++;
15400  line_width = 0;
15401  line = text + text_len;
15402  line_offset += row_height;
15403  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
15404  continue;
15405  }
15406  if (unicode == '\r') {
15407  text_len++;
15408  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15409  continue;
15410  }
15411  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15412  line_width += (float)glyph_width;
15413  text_len += glyph_len;
15414  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15415  continue;
15416  }
15417  if (line_width > 0) {
15418  /* draw last line */
15419  struct nk_rect label;
15420  label.y = pos_y + line_offset;
15421  label.h = row_height;
15422  label.w = line_width;
15423  label.x = pos_x;
15424  if (!line_count)
15425  label.x += x_offset;
15426 
15427  if (is_selected)
15428  nk_fill_rect(out, label, 0, background);
15429  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15430  &txt, NK_TEXT_LEFT, font);
15431  }}
15432 }
15433 
15434 NK_INTERN nk_flags
15435 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
15436  struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
15437  struct nk_text_edit *edit, const struct nk_style_edit *style,
15438  struct nk_input *in, const struct nk_user_font *font)
15439 {
15440  struct nk_rect area;
15441  nk_flags ret = 0;
15442  float row_height;
15443  char prev_state = 0;
15444  char is_hovered = 0;
15445  char select_all = 0;
15446  char cursor_follow = 0;
15447  struct nk_rect old_clip;
15448  struct nk_rect clip;
15449 
15450  NK_ASSERT(state);
15451  NK_ASSERT(out);
15452  NK_ASSERT(style);
15453  if (!state || !out || !style)
15454  return ret;
15455 
15456  /* visible text area calculation */
15457  area.x = bounds.x + style->padding.x + style->border;
15458  area.y = bounds.y + style->padding.y + style->border;
15459  area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
15460  area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
15461  if (flags & NK_EDIT_MULTILINE)
15462  area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
15463  row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
15464 
15465  /* calculate clipping rectangle */
15466  old_clip = out->clip;
15467  nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
15468 
15469  /* update edit state */
15470  prev_state = (char)edit->active;
15471  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
15473  edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
15474  bounds.x, bounds.y, bounds.w, bounds.h);
15475  }
15476 
15477  /* (de)activate text editor */
15478  if (!prev_state && edit->active) {
15479  const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
15481  nk_textedit_clear_state(edit, type, filter);
15482  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
15484  if (flags & NK_EDIT_AUTO_SELECT)
15485  select_all = nk_true;
15486  if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
15487  edit->cursor = edit->string.len;
15488  in = 0;
15489  }
15490  } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15491  if (flags & NK_EDIT_READ_ONLY)
15492  edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15493 
15494  ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
15495  if (prev_state != edit->active)
15496  ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
15497 
15498  /* handle user input */
15499  if (edit->active && in)
15500  {
15501  int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
15502  const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
15503  const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
15504 
15505  /* mouse click handler */
15506  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
15507  if (select_all) {
15508  nk_textedit_select_all(edit);
15509  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15511  nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
15512  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15513  (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
15514  nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
15515  cursor_follow = nk_true;
15516  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
15518  nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
15519  nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
15520  cursor_follow = nk_true;
15521  }
15522 
15523  {int i; /* keyboard input */
15524  int old_mode = edit->mode;
15525  for (i = 0; i < NK_KEY_MAX; ++i) {
15526  if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
15527  if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
15528  nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
15529  cursor_follow = nk_true;
15530  }
15531  }
15532  if (old_mode != edit->mode) {
15533  in->keyboard.text_len = 0;
15534  }}
15535 
15536  /* text input */
15537  edit->filter = filter;
15538  if (in->keyboard.text_len) {
15540  cursor_follow = nk_true;
15541  in->keyboard.text_len = 0;
15542  }
15543 
15544  /* enter key handler */
15546  cursor_follow = nk_true;
15547  if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
15548  nk_textedit_text(edit, "\n", 1);
15549  else if (flags & NK_EDIT_SIG_ENTER)
15550  ret |= NK_EDIT_COMMITED;
15551  else nk_textedit_text(edit, "\n", 1);
15552  }
15553 
15554  /* cut & copy handler */
15555  {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
15556  int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
15557  if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
15558  {
15559  int glyph_len;
15560  nk_rune unicode;
15561  const char *text;
15562  int b = edit->select_start;
15563  int e = edit->select_end;
15564 
15565  int begin = NK_MIN(b, e);
15566  int end = NK_MAX(b, e);
15567  text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
15568  if (edit->clip.copy)
15569  edit->clip.copy(edit->clip.userdata, text, end - begin);
15570  if (cut && !(flags & NK_EDIT_READ_ONLY)){
15571  nk_textedit_cut(edit);
15572  cursor_follow = nk_true;
15573  }
15574  }}
15575 
15576  /* paste handler */
15577  {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
15578  if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
15579  edit->clip.paste(edit->clip.userdata, edit);
15580  cursor_follow = nk_true;
15581  }}
15582 
15583  /* tab handler */
15584  {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
15585  if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
15586  nk_textedit_text(edit, " ", 4);
15587  cursor_follow = nk_true;
15588  }}
15589  }
15590 
15591  /* set widget state */
15592  if (edit->active)
15593  *state = NK_WIDGET_STATE_ACTIVE;
15594  else nk_widget_state_reset(state);
15595 
15596  if (is_hovered)
15597  *state |= NK_WIDGET_STATE_HOVERED;
15598 
15599  /* DRAW EDIT */
15600  {const char *text = nk_str_get_const(&edit->string);
15601  int len = nk_str_len_char(&edit->string);
15602 
15603  {/* select background colors/images */
15604  const struct nk_style_item *background;
15605  if (*state & NK_WIDGET_STATE_ACTIVED)
15606  background = &style->active;
15607  else if (*state & NK_WIDGET_STATE_HOVER)
15608  background = &style->hover;
15609  else background = &style->normal;
15610 
15611  /* draw background frame */
15612  if (background->type == NK_STYLE_ITEM_COLOR) {
15613  nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
15614  nk_fill_rect(out, bounds, style->rounding, background->data.color);
15615  } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
15616 
15617  area.w = NK_MAX(0, area.w - style->cursor_size);
15618  if (edit->active)
15619  {
15620  int total_lines = 1;
15621  struct nk_vec2 text_size = nk_vec2(0,0);
15622 
15623  /* text pointer positions */
15624  const char *cursor_ptr = 0;
15625  const char *select_begin_ptr = 0;
15626  const char *select_end_ptr = 0;
15627 
15628  /* 2D pixel positions */
15629  struct nk_vec2 cursor_pos = nk_vec2(0,0);
15630  struct nk_vec2 selection_offset_start = nk_vec2(0,0);
15631  struct nk_vec2 selection_offset_end = nk_vec2(0,0);
15632 
15633  int selection_begin = NK_MIN(edit->select_start, edit->select_end);
15634  int selection_end = NK_MAX(edit->select_start, edit->select_end);
15635 
15636  /* calculate total line count + total space + cursor/selection position */
15637  float line_width = 0.0f;
15638  if (text && len)
15639  {
15640  /* utf8 encoding */
15641  float glyph_width;
15642  int glyph_len = 0;
15643  nk_rune unicode = 0;
15644  int text_len = 0;
15645  int glyphs = 0;
15646  int row_begin = 0;
15647 
15648  glyph_len = nk_utf_decode(text, &unicode, len);
15649  glyph_width = font->width(font->userdata, font->height, text, glyph_len);
15650  line_width = 0;
15651 
15652  /* iterate all lines */
15653  while ((text_len < len) && glyph_len)
15654  {
15655  /* set cursor 2D position and line */
15656  if (!cursor_ptr && glyphs == edit->cursor)
15657  {
15658  int glyph_offset;
15659  struct nk_vec2 out_offset;
15660  struct nk_vec2 row_size;
15661  const char *remaining;
15662 
15663  /* calculate 2d position */
15664  cursor_pos.y = (float)(total_lines-1) * row_height;
15665  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15666  text_len-row_begin, row_height, &remaining,
15667  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15668  cursor_pos.x = row_size.x;
15669  cursor_ptr = text + text_len;
15670  }
15671 
15672  /* set start selection 2D position and line */
15673  if (!select_begin_ptr && edit->select_start != edit->select_end &&
15674  glyphs == selection_begin)
15675  {
15676  int glyph_offset;
15677  struct nk_vec2 out_offset;
15678  struct nk_vec2 row_size;
15679  const char *remaining;
15680 
15681  /* calculate 2d position */
15682  selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
15683  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15684  text_len-row_begin, row_height, &remaining,
15685  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15686  selection_offset_start.x = row_size.x;
15687  select_begin_ptr = text + text_len;
15688  }
15689 
15690  /* set end selection 2D position and line */
15691  if (!select_end_ptr && edit->select_start != edit->select_end &&
15692  glyphs == selection_end)
15693  {
15694  int glyph_offset;
15695  struct nk_vec2 out_offset;
15696  struct nk_vec2 row_size;
15697  const char *remaining;
15698 
15699  /* calculate 2d position */
15700  selection_offset_end.y = (float)(total_lines-1) * row_height;
15701  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15702  text_len-row_begin, row_height, &remaining,
15703  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15704  selection_offset_end.x = row_size.x;
15705  select_end_ptr = text + text_len;
15706  }
15707  if (unicode == '\n') {
15708  text_size.x = NK_MAX(text_size.x, line_width);
15709  total_lines++;
15710  line_width = 0;
15711  text_len++;
15712  glyphs++;
15713  row_begin = text_len;
15714  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15715  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15716  continue;
15717  }
15718 
15719  glyphs++;
15720  text_len += glyph_len;
15721  line_width += (float)glyph_width;
15722 
15723  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15724  glyph_width = font->width(font->userdata, font->height,
15725  text+text_len, glyph_len);
15726  continue;
15727  }
15728  text_size.y = (float)total_lines * row_height;
15729 
15730  /* handle case when cursor is at end of text buffer */
15731  if (!cursor_ptr && edit->cursor == edit->string.len) {
15732  cursor_pos.x = line_width;
15733  cursor_pos.y = text_size.y - row_height;
15734  }
15735  }
15736  {
15737  /* scrollbar */
15738  if (cursor_follow)
15739  {
15740  /* update scrollbar to follow cursor */
15741  if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
15742  /* horizontal scroll */
15743  const float scroll_increment = area.w * 0.25f;
15744  if (cursor_pos.x < edit->scrollbar.x)
15745  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
15746  if (cursor_pos.x >= edit->scrollbar.x + area.w)
15747  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x);
15748  } else edit->scrollbar.x = 0;
15749 
15750  if (flags & NK_EDIT_MULTILINE) {
15751  /* vertical scroll */
15752  if (cursor_pos.y < edit->scrollbar.y)
15753  edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
15754  if (cursor_pos.y >= edit->scrollbar.y + area.h)
15755  edit->scrollbar.y = edit->scrollbar.y + row_height;
15756  } else edit->scrollbar.y = 0;
15757  }
15758 
15759  /* scrollbar widget */
15760  if (flags & NK_EDIT_MULTILINE)
15761  {
15762  nk_flags ws;
15763  struct nk_rect scroll;
15764  float scroll_target;
15765  float scroll_offset;
15766  float scroll_step;
15767  float scroll_inc;
15768 
15769  scroll = area;
15770  scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
15771  scroll.w = style->scrollbar_size.x;
15772 
15773  scroll_offset = edit->scrollbar.y;
15774  scroll_step = scroll.h * 0.10f;
15775  scroll_inc = scroll.h * 0.01f;
15776  scroll_target = text_size.y;
15777  edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
15778  scroll_offset, scroll_target, scroll_step, scroll_inc,
15779  &style->scrollbar, in, font);
15780  }
15781  }
15782 
15783  /* draw text */
15784  {struct nk_color background_color;
15785  struct nk_color text_color;
15786  struct nk_color sel_background_color;
15787  struct nk_color sel_text_color;
15788  struct nk_color cursor_color;
15789  struct nk_color cursor_text_color;
15790  const struct nk_style_item *background;
15791  nk_push_scissor(out, clip);
15792 
15793  /* select correct colors to draw */
15794  if (*state & NK_WIDGET_STATE_ACTIVED) {
15795  background = &style->active;
15796  text_color = style->text_active;
15797  sel_text_color = style->selected_text_hover;
15798  sel_background_color = style->selected_hover;
15799  cursor_color = style->cursor_hover;
15800  cursor_text_color = style->cursor_text_hover;
15801  } else if (*state & NK_WIDGET_STATE_HOVER) {
15802  background = &style->hover;
15803  text_color = style->text_hover;
15804  sel_text_color = style->selected_text_hover;
15805  sel_background_color = style->selected_hover;
15806  cursor_text_color = style->cursor_text_hover;
15807  cursor_color = style->cursor_hover;
15808  } else {
15809  background = &style->normal;
15810  text_color = style->text_normal;
15811  sel_text_color = style->selected_text_normal;
15812  sel_background_color = style->selected_normal;
15813  cursor_color = style->cursor_normal;
15814  cursor_text_color = style->cursor_text_normal;
15815  }
15816  if (background->type == NK_STYLE_ITEM_IMAGE)
15817  background_color = nk_rgba(0,0,0,0);
15818  else background_color = background->data.color;
15819 
15820 
15821  if (edit->select_start == edit->select_end) {
15822  /* no selection so just draw the complete text */
15823  const char *begin = nk_str_get_const(&edit->string);
15824  int l = nk_str_len_char(&edit->string);
15825  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15826  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15827  background_color, text_color, nk_false);
15828  } else {
15829  /* edit has selection so draw 1-3 text chunks */
15830  if (edit->select_start != edit->select_end && selection_begin > 0){
15831  /* draw unselected text before selection */
15832  const char *begin = nk_str_get_const(&edit->string);
15833  NK_ASSERT(select_begin_ptr);
15834  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15835  area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
15836  row_height, font, background_color, text_color, nk_false);
15837  }
15838  if (edit->select_start != edit->select_end) {
15839  /* draw selected text */
15840  NK_ASSERT(select_begin_ptr);
15841  if (!select_end_ptr) {
15842  const char *begin = nk_str_get_const(&edit->string);
15843  select_end_ptr = begin + nk_str_len_char(&edit->string);
15844  }
15845  nk_edit_draw_text(out, style,
15846  area.x - edit->scrollbar.x,
15847  area.y + selection_offset_start.y - edit->scrollbar.y,
15848  selection_offset_start.x,
15849  select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
15850  row_height, font, sel_background_color, sel_text_color, nk_true);
15851  }
15852  if ((edit->select_start != edit->select_end &&
15853  selection_end < edit->string.len))
15854  {
15855  /* draw unselected text after selected text */
15856  const char *begin = select_end_ptr;
15857  const char *end = nk_str_get_const(&edit->string) +
15858  nk_str_len_char(&edit->string);
15859  NK_ASSERT(select_end_ptr);
15860  nk_edit_draw_text(out, style,
15861  area.x - edit->scrollbar.x,
15862  area.y + selection_offset_end.y - edit->scrollbar.y,
15863  selection_offset_end.x,
15864  begin, (int)(end - begin), row_height, font,
15865  background_color, text_color, nk_true);
15866  }
15867  }
15868 
15869  /* cursor */
15870  if (edit->select_start == edit->select_end)
15871  {
15872  if (edit->cursor >= nk_str_len(&edit->string) ||
15873  (cursor_ptr && *cursor_ptr == '\n')) {
15874  /* draw cursor at end of line */
15875  struct nk_rect cursor;
15876  cursor.w = style->cursor_size;
15877  cursor.h = font->height;
15878  cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
15879  cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
15880  cursor.y -= edit->scrollbar.y;
15881  nk_fill_rect(out, cursor, 0, cursor_color);
15882  } else {
15883  /* draw cursor inside text */
15884  int glyph_len;
15885  struct nk_rect label;
15886  struct nk_text txt;
15887 
15888  nk_rune unicode;
15889  NK_ASSERT(cursor_ptr);
15890  glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
15891 
15892  label.x = area.x + cursor_pos.x - edit->scrollbar.x;
15893  label.y = area.y + cursor_pos.y - edit->scrollbar.y;
15894  label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
15895  label.h = row_height;
15896 
15897  txt.padding = nk_vec2(0,0);
15898  txt.background = cursor_color;;
15899  txt.text = cursor_text_color;
15900  nk_fill_rect(out, label, 0, cursor_color);
15901  nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
15902  }
15903  }}
15904  } else {
15905  /* not active so just draw text */
15906  int l = nk_str_len_char(&edit->string);
15907  const char *begin = nk_str_get_const(&edit->string);
15908 
15909  const struct nk_style_item *background;
15910  struct nk_color background_color;
15911  struct nk_color text_color;
15912  nk_push_scissor(out, clip);
15913  if (*state & NK_WIDGET_STATE_ACTIVED) {
15914  background = &style->active;
15915  text_color = style->text_active;
15916  } else if (*state & NK_WIDGET_STATE_HOVER) {
15917  background = &style->hover;
15918  text_color = style->text_hover;
15919  } else {
15920  background = &style->normal;
15921  text_color = style->text_normal;
15922  }
15923  if (background->type == NK_STYLE_ITEM_IMAGE)
15924  background_color = nk_rgba(0,0,0,0);
15925  else background_color = background->data.color;
15926  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15927  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15928  background_color, text_color, nk_false);
15929  }
15930  nk_push_scissor(out, old_clip);}
15931  return ret;
15932 }
15933 
15934 /* ===============================================================
15935  *
15936  * PROPERTY
15937  *
15938  * ===============================================================*/
15939 enum nk_property_status {
15940  NK_PROPERTY_DEFAULT,
15941  NK_PROPERTY_EDIT,
15942  NK_PROPERTY_DRAG
15943 };
15944 enum nk_property_filter {
15945  NK_FILTER_INT,
15946  NK_FILTER_FLOAT
15947 };
15948 enum nk_property_kind {
15949  NK_PROPERTY_INT,
15950  NK_PROPERTY_FLOAT,
15951  NK_PROPERTY_DOUBLE
15952 };
15953 union nk_property {
15954  int i;
15955  float f;
15956  double d;
15957 };
15958 struct nk_property_variant {
15959  enum nk_property_kind kind;
15960  union nk_property value;
15961  union nk_property min_value;
15962  union nk_property max_value;
15963  union nk_property step;
15964 };
15965 
15966 NK_INTERN void
15967 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
15968  struct nk_rect drag, struct nk_property_variant *variant,
15969  float inc_per_pixel)
15970 {
15971  int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
15972  int left_mouse_click_in_cursor = in &&
15974 
15975  nk_widget_state_reset(state);
15976  if (nk_input_is_mouse_hovering_rect(in, drag))
15977  *state = NK_WIDGET_STATE_HOVERED;
15978 
15979  if (left_mouse_down && left_mouse_click_in_cursor) {
15980  float delta, pixels;
15981  pixels = in->mouse.delta.x;
15982  delta = pixels * inc_per_pixel;
15983  switch (variant->kind) {
15984  default: break;
15985  case NK_PROPERTY_INT:
15986  variant->value.i = variant->value.i + (int)delta;
15987  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
15988  break;
15989  case NK_PROPERTY_FLOAT:
15990  variant->value.f = variant->value.f + (float)delta;
15991  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
15992  break;
15993  case NK_PROPERTY_DOUBLE:
15994  variant->value.d = variant->value.d + (double)delta;
15995  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
15996  break;
15997  }
15998  *state = NK_WIDGET_STATE_ACTIVE;
15999  }
16000  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag))
16001  *state |= NK_WIDGET_STATE_ENTERED;
16002  else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
16003  *state |= NK_WIDGET_STATE_LEFT;
16004 }
16005 
16006 NK_INTERN void
16007 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
16008  struct nk_rect property, struct nk_rect label, struct nk_rect edit,
16009  struct nk_rect empty, int *state, struct nk_property_variant *variant,
16010  float inc_per_pixel)
16011 {
16012  if (in && *state == NK_PROPERTY_DEFAULT) {
16013  if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
16014  *state = NK_PROPERTY_EDIT;
16016  *state = NK_PROPERTY_DRAG;
16018  *state = NK_PROPERTY_DRAG;
16019  }
16020  if (*state == NK_PROPERTY_DRAG) {
16021  nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
16022  if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
16023  }
16024 }
16025 
16026 NK_INTERN void
16027 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
16028  const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
16029  const char *name, int len, const struct nk_user_font *font)
16030 {
16031  struct nk_text text;
16032  const struct nk_style_item *background;
16033 
16034  /* select correct background and text color */
16035  if (state & NK_WIDGET_STATE_ACTIVED) {
16036  background = &style->active;
16037  text.text = style->label_active;
16038  } else if (state & NK_WIDGET_STATE_HOVER) {
16039  background = &style->hover;
16040  text.text = style->label_hover;
16041  } else {
16042  background = &style->normal;
16043  text.text = style->label_normal;
16044  }
16045 
16046  /* draw background */
16047  if (background->type == NK_STYLE_ITEM_IMAGE) {
16048  nk_draw_image(out, *bounds, &background->data.image, nk_white);
16049  text.background = nk_rgba(0,0,0,0);
16050  } else {
16051  text.background = background->data.color;
16052  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16053  nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
16054  }
16055 
16056  /* draw label */
16057  text.padding = nk_vec2(0,0);
16058  nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
16059 }
16060 
16061 NK_INTERN void
16062 nk_do_property(nk_flags *ws,
16063  struct nk_command_buffer *out, struct nk_rect property,
16064  const char *name, struct nk_property_variant *variant,
16065  float inc_per_pixel, char *buffer, int *len,
16066  int *state, int *cursor, int *select_begin, int *select_end,
16067  const struct nk_style_property *style,
16068  enum nk_property_filter filter, struct nk_input *in,
16069  const struct nk_user_font *font, struct nk_text_edit *text_edit,
16070  enum nk_button_behavior behavior)
16071 {
16072  const nk_plugin_filter filters[] = {
16075  };
16076  int active, old;
16077  int num_len, name_len;
16078  char string[NK_MAX_NUMBER_BUFFER];
16079  float size;
16080 
16081  char *dst = 0;
16082  int *length;
16083 
16084  struct nk_rect left;
16085  struct nk_rect right;
16086  struct nk_rect label;
16087  struct nk_rect edit;
16088  struct nk_rect empty;
16089 
16090  /* left decrement button */
16091  left.h = font->height/2;
16092  left.w = left.h;
16093  left.x = property.x + style->border + style->padding.x;
16094  left.y = property.y + style->border + property.h/2.0f - left.h/2;
16095 
16096  /* text label */
16097  name_len = nk_strlen(name);
16098  size = font->width(font->userdata, font->height, name, name_len);
16099  label.x = left.x + left.w + style->padding.x;
16100  label.w = (float)size + 2 * style->padding.x;
16101  label.y = property.y + style->border + style->padding.y;
16102  label.h = property.h - (2 * style->border + 2 * style->padding.y);
16103 
16104  /* right increment button */
16105  right.y = left.y;
16106  right.w = left.w;
16107  right.h = left.h;
16108  right.x = property.x + property.w - (right.w + style->padding.x);
16109 
16110  /* edit */
16111  if (*state == NK_PROPERTY_EDIT) {
16112  size = font->width(font->userdata, font->height, buffer, *len);
16113  size += style->edit.cursor_size;
16114  length = len;
16115  dst = buffer;
16116  } else {
16117  switch (variant->kind) {
16118  default: break;
16119  case NK_PROPERTY_INT:
16120  nk_itoa(string, variant->value.i);
16121  num_len = nk_strlen(string);
16122  break;
16123  case NK_PROPERTY_FLOAT:
16124  nk_dtoa(string, (double)variant->value.f);
16125  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
16126  break;
16127  case NK_PROPERTY_DOUBLE:
16128  nk_dtoa(string, variant->value.d);
16129  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
16130  break;
16131  }
16132  size = font->width(font->userdata, font->height, string, num_len);
16133  dst = string;
16134  length = &num_len;
16135  }
16136 
16137  edit.w = (float)size + 2 * style->padding.x;
16138  edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
16139  edit.x = right.x - (edit.w + style->padding.x);
16140  edit.y = property.y + style->border;
16141  edit.h = property.h - (2 * style->border);
16142 
16143  /* empty left space activator */
16144  empty.w = edit.x - (label.x + label.w);
16145  empty.x = label.x + label.w;
16146  empty.y = property.y;
16147  empty.h = property.h;
16148 
16149  /* update property */
16150  old = (*state == NK_PROPERTY_EDIT);
16151  nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
16152 
16153  /* draw property */
16154  if (style->draw_begin) style->draw_begin(out, style->userdata);
16155  nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
16156  if (style->draw_end) style->draw_end(out, style->userdata);
16157 
16158  /* execute right button */
16159  if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
16160  switch (variant->kind) {
16161  default: break;
16162  case NK_PROPERTY_INT:
16163  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
16164  case NK_PROPERTY_FLOAT:
16165  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
16166  case NK_PROPERTY_DOUBLE:
16167  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
16168  }
16169  }
16170  /* execute left button */
16171  if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
16172  switch (variant->kind) {
16173  default: break;
16174  case NK_PROPERTY_INT:
16175  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
16176  case NK_PROPERTY_FLOAT:
16177  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
16178  case NK_PROPERTY_DOUBLE:
16179  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
16180  }
16181  }
16182  if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
16183  /* property has been activated so setup buffer */
16184  NK_MEMCPY(buffer, dst, (nk_size)*length);
16185  *cursor = nk_utf_len(buffer, *length);
16186  *len = *length;
16187  length = len;
16188  dst = buffer;
16189  active = 0;
16190  } else active = (*state == NK_PROPERTY_EDIT);
16191 
16192  /* execute and run text edit field */
16193  nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
16194  text_edit->active = (unsigned char)active;
16195  text_edit->string.len = *length;
16196  text_edit->cursor = NK_CLAMP(0, *cursor, *length);
16197  text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
16198  text_edit->select_end = NK_CLAMP(0,*select_end, *length);
16199  text_edit->string.buffer.allocated = (nk_size)*length;
16201  text_edit->string.buffer.memory.ptr = dst;
16202  text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
16203  text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
16204  nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
16205  filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
16206 
16207  *length = text_edit->string.len;
16208  *cursor = text_edit->cursor;
16209  *select_begin = text_edit->select_start;
16210  *select_end = text_edit->select_end;
16211  if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
16212  text_edit->active = nk_false;
16213 
16214  if (active && !text_edit->active) {
16215  /* property is now not active so convert edit text to value*/
16216  *state = NK_PROPERTY_DEFAULT;
16217  buffer[*len] = '\0';
16218  switch (variant->kind) {
16219  default: break;
16220  case NK_PROPERTY_INT:
16221  variant->value.i = nk_strtoi(buffer, 0);
16222  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
16223  break;
16224  case NK_PROPERTY_FLOAT:
16225  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16226  variant->value.f = nk_strtof(buffer, 0);
16227  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
16228  break;
16229  case NK_PROPERTY_DOUBLE:
16230  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16231  variant->value.d = nk_strtod(buffer, 0);
16232  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
16233  break;
16234  }
16235  }
16236 }
16237 /* ===============================================================
16238  *
16239  * COLOR PICKER
16240  *
16241  * ===============================================================*/
16242 NK_INTERN int
16243 nk_color_picker_behavior(nk_flags *state,
16244  const struct nk_rect *bounds, const struct nk_rect *matrix,
16245  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16246  struct nk_color *color, const struct nk_input *in)
16247 {
16248  float hsva[4];
16249  int value_changed = 0;
16250  int hsv_changed = 0;
16251 
16252  NK_ASSERT(state);
16253  NK_ASSERT(matrix);
16254  NK_ASSERT(hue_bar);
16255  NK_ASSERT(color);
16256 
16257  /* color matrix */
16258  nk_color_hsva_fv(hsva, *color);
16259  if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) {
16260  hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
16261  hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
16262  value_changed = hsv_changed = 1;
16263  }
16264 
16265  /* hue bar */
16266  if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
16267  hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
16268  value_changed = hsv_changed = 1;
16269  }
16270 
16271  /* alpha bar */
16272  if (alpha_bar) {
16273  if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
16274  hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
16275  value_changed = 1;
16276  }
16277  }
16278  nk_widget_state_reset(state);
16279  if (hsv_changed) {
16280  *color = nk_hsva_fv(hsva);
16281  *state = NK_WIDGET_STATE_ACTIVE;
16282  }
16283  if (value_changed) {
16284  color->a = (nk_byte)(hsva[3] * 255.0f);
16285  *state = NK_WIDGET_STATE_ACTIVE;
16286  }
16287 
16288  /* set color picker widget state */
16289  if (nk_input_is_mouse_hovering_rect(in, *bounds))
16290  *state = NK_WIDGET_STATE_HOVERED;
16291  if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16292  *state |= NK_WIDGET_STATE_ENTERED;
16293  else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16294  *state |= NK_WIDGET_STATE_LEFT;
16295  return value_changed;
16296 }
16297 
16298 NK_INTERN void
16299 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
16300  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16301  struct nk_color color)
16302 {
16303  NK_STORAGE const struct nk_color black = {0,0,0,255};
16304  NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
16305  NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
16306 
16307  const float crosshair_size = 7.0f;
16308  struct nk_color temp;
16309  float hsva[4];
16310  float line_y;
16311  int i;
16312 
16313  NK_ASSERT(o);
16314  NK_ASSERT(matrix);
16315  NK_ASSERT(hue_bar);
16316 
16317  /* draw hue bar */
16318  nk_color_hsv_fv(hsva, color);
16319  for (i = 0; i < 6; ++i) {
16320  NK_GLOBAL const struct nk_color hue_colors[] = {
16321  {255, 0, 0, 255},
16322  {255,255,0,255},
16323  {0,255,0,255},
16324  {0, 255,255,255},
16325  {0,0,255,255},
16326  {255, 0, 255, 255},
16327  {255, 0, 0, 255}
16328  };
16330  nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
16331  hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
16332  hue_colors[i+1], hue_colors[i+1]);
16333  }
16334  line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
16335  nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
16336  line_y, 1, nk_rgb(255,255,255));
16337 
16338  /* draw alpha bar */
16339  if (alpha_bar) {
16340  float alpha = NK_SATURATE((float)color.a/255.0f);
16341  line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
16342 
16343  nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
16344  nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
16345  line_y, 1, nk_rgb(255,255,255));
16346  }
16347 
16348  /* draw color matrix */
16349  temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
16350  nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
16351  nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
16352 
16353  /* draw cross-hair */
16354  {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
16355  p.x = (float)(int)(matrix->x + S * matrix->w);
16356  p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
16357  nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
16358  nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
16359  nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
16360  nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
16361 }
16362 
16363 NK_INTERN int
16364 nk_do_color_picker(nk_flags *state,
16365  struct nk_command_buffer *out, struct nk_color *color,
16366  enum nk_color_format fmt, struct nk_rect bounds,
16367  struct nk_vec2 padding, const struct nk_input *in,
16368  const struct nk_user_font *font)
16369 {
16370  int ret = 0;
16371  struct nk_rect matrix;
16372  struct nk_rect hue_bar;
16373  struct nk_rect alpha_bar;
16374  float bar_w;
16375 
16376  NK_ASSERT(out);
16377  NK_ASSERT(color);
16378  NK_ASSERT(state);
16379  NK_ASSERT(font);
16380  if (!out || !color || !state || !font)
16381  return ret;
16382 
16383  bar_w = font->height;
16384  bounds.x += padding.x;
16385  bounds.y += padding.x;
16386  bounds.w -= 2 * padding.x;
16387  bounds.h -= 2 * padding.y;
16388 
16389  matrix.x = bounds.x;
16390  matrix.y = bounds.y;
16391  matrix.h = bounds.h;
16392  matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
16393 
16394  hue_bar.w = bar_w;
16395  hue_bar.y = bounds.y;
16396  hue_bar.h = matrix.h;
16397  hue_bar.x = matrix.x + matrix.w + padding.x;
16398 
16399  alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
16400  alpha_bar.y = bounds.y;
16401  alpha_bar.w = bar_w;
16402  alpha_bar.h = matrix.h;
16403 
16404  ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
16405  (fmt == NK_RGBA) ? &alpha_bar:0, color, in);
16406  nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color);
16407  return ret;
16408 }
16409 
16410 /* ==============================================================
16411  *
16412  * STYLE
16413  *
16414  * ===============================================================*/
16415 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);}
16416 #define NK_COLOR_MAP(NK_COLOR)\
16417  NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
16418  NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
16419  NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
16420  NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
16421  NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
16422  NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
16423  NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
16424  NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
16425  NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
16426  NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
16427  NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
16428  NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
16429  NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
16430  NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
16431  NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
16432  NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
16433  NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
16434  NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
16435  NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
16436  NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
16437  NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
16438  NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
16439  NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0, 0, 255) \
16440  NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
16441  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
16442  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \
16443  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \
16444  NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255)
16445 
16446 NK_GLOBAL const struct nk_color
16447 nk_default_color_style[NK_COLOR_COUNT] = {
16448 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
16449  NK_COLOR_MAP(NK_COLOR)
16450 #undef NK_COLOR
16451 };
16452 
16453 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
16454 #define NK_COLOR(a,b,c,d,e) #a,
16455  NK_COLOR_MAP(NK_COLOR)
16456 #undef NK_COLOR
16457 };
16458 
16460 {return nk_color_names[c];}
16461 
16463 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;}
16464 
16466 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;}
16467 
16469 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;}
16470 
16471 NK_API void
16472 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
16473 {
16474  struct nk_style *style;
16475  struct nk_style_text *text;
16476  struct nk_style_button *button;
16477  struct nk_style_toggle *toggle;
16478  struct nk_style_selectable *select;
16479  struct nk_style_slider *slider;
16480  struct nk_style_progress *prog;
16481  struct nk_style_scrollbar *scroll;
16482  struct nk_style_edit *edit;
16483  struct nk_style_property *property;
16484  struct nk_style_combo *combo;
16485  struct nk_style_chart *chart;
16486  struct nk_style_tab *tab;
16487  struct nk_style_window *win;
16488 
16489  NK_ASSERT(ctx);
16490  if (!ctx) return;
16491  style = &ctx->style;
16492  table = (!table) ? nk_default_color_style: table;
16493 
16494  /* default text */
16495  text = &style->text;
16496  text->color = table[NK_COLOR_TEXT];
16497  text->padding = nk_vec2(0,0);
16498 
16499  /* default button */
16500  button = &style->button;
16501  nk_zero_struct(*button);
16502  button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]);
16505  button->border_color = table[NK_COLOR_BORDER];
16506  button->text_background = table[NK_COLOR_BUTTON];
16507  button->text_normal = table[NK_COLOR_TEXT];
16508  button->text_hover = table[NK_COLOR_TEXT];
16509  button->text_active = table[NK_COLOR_TEXT];
16510  button->padding = nk_vec2(2.0f,2.0f);
16511  button->image_padding = nk_vec2(0.0f,0.0f);
16512  button->touch_padding = nk_vec2(0.0f, 0.0f);
16513  button->userdata = nk_handle_ptr(0);
16514  button->text_alignment = NK_TEXT_CENTERED;
16515  button->border = 1.0f;
16516  button->rounding = 4.0f;
16517  button->draw_begin = 0;
16518  button->draw_end = 0;
16519 
16520  /* contextual button */
16521  button = &style->contextual_button;
16522  nk_zero_struct(*button);
16523  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16526  button->border_color = table[NK_COLOR_WINDOW];
16527  button->text_background = table[NK_COLOR_WINDOW];
16528  button->text_normal = table[NK_COLOR_TEXT];
16529  button->text_hover = table[NK_COLOR_TEXT];
16530  button->text_active = table[NK_COLOR_TEXT];
16531  button->padding = nk_vec2(2.0f,2.0f);
16532  button->touch_padding = nk_vec2(0.0f,0.0f);
16533  button->userdata = nk_handle_ptr(0);
16534  button->text_alignment = NK_TEXT_CENTERED;
16535  button->border = 0.0f;
16536  button->rounding = 0.0f;
16537  button->draw_begin = 0;
16538  button->draw_end = 0;
16539 
16540  /* menu button */
16541  button = &style->menu_button;
16542  nk_zero_struct(*button);
16543  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16544  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
16545  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
16546  button->border_color = table[NK_COLOR_WINDOW];
16547  button->text_background = table[NK_COLOR_WINDOW];
16548  button->text_normal = table[NK_COLOR_TEXT];
16549  button->text_hover = table[NK_COLOR_TEXT];
16550  button->text_active = table[NK_COLOR_TEXT];
16551  button->padding = nk_vec2(2.0f,2.0f);
16552  button->touch_padding = nk_vec2(0.0f,0.0f);
16553  button->userdata = nk_handle_ptr(0);
16554  button->text_alignment = NK_TEXT_CENTERED;
16555  button->border = 0.0f;
16556  button->rounding = 1.0f;
16557  button->draw_begin = 0;
16558  button->draw_end = 0;
16559 
16560  /* checkbox toggle */
16561  toggle = &style->checkbox;
16562  nk_zero_struct(*toggle);
16563  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16568  toggle->userdata = nk_handle_ptr(0);
16569  toggle->text_background = table[NK_COLOR_WINDOW];
16570  toggle->text_normal = table[NK_COLOR_TEXT];
16571  toggle->text_hover = table[NK_COLOR_TEXT];
16572  toggle->text_active = table[NK_COLOR_TEXT];
16573  toggle->padding = nk_vec2(2.0f, 2.0f);
16574  toggle->touch_padding = nk_vec2(0,0);
16575  toggle->border_color = nk_rgba(0,0,0,0);
16576  toggle->border = 0.0f;
16577  toggle->spacing = 4;
16578 
16579  /* option toggle */
16580  toggle = &style->option;
16581  nk_zero_struct(*toggle);
16582  toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]);
16587  toggle->userdata = nk_handle_ptr(0);
16588  toggle->text_background = table[NK_COLOR_WINDOW];
16589  toggle->text_normal = table[NK_COLOR_TEXT];
16590  toggle->text_hover = table[NK_COLOR_TEXT];
16591  toggle->text_active = table[NK_COLOR_TEXT];
16592  toggle->padding = nk_vec2(3.0f, 3.0f);
16593  toggle->touch_padding = nk_vec2(0,0);
16594  toggle->border_color = nk_rgba(0,0,0,0);
16595  toggle->border = 0.0f;
16596  toggle->spacing = 4;
16597 
16598  /* selectable */
16599  select = &style->selectable;
16600  nk_zero_struct(*select);
16601  select->normal = nk_style_item_color(table[NK_COLOR_SELECT]);
16602  select->hover = nk_style_item_color(table[NK_COLOR_SELECT]);
16603  select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]);
16607  select->text_normal = table[NK_COLOR_TEXT];
16608  select->text_hover = table[NK_COLOR_TEXT];
16609  select->text_pressed = table[NK_COLOR_TEXT];
16610  select->text_normal_active = table[NK_COLOR_TEXT];
16611  select->text_hover_active = table[NK_COLOR_TEXT];
16612  select->text_pressed_active = table[NK_COLOR_TEXT];
16613  select->padding = nk_vec2(2.0f,2.0f);
16614  select->touch_padding = nk_vec2(0,0);
16615  select->userdata = nk_handle_ptr(0);
16616  select->rounding = 0.0f;
16617  select->draw_begin = 0;
16618  select->draw_end = 0;
16619 
16620  /* slider */
16621  slider = &style->slider;
16622  nk_zero_struct(*slider);
16623  slider->normal = nk_style_item_hide();
16624  slider->hover = nk_style_item_hide();
16625  slider->active = nk_style_item_hide();
16626  slider->bar_normal = table[NK_COLOR_SLIDER];
16627  slider->bar_hover = table[NK_COLOR_SLIDER];
16628  slider->bar_active = table[NK_COLOR_SLIDER];
16629  slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR];
16635  slider->cursor_size = nk_vec2(16,16);
16636  slider->padding = nk_vec2(2,2);
16637  slider->spacing = nk_vec2(2,2);
16638  slider->userdata = nk_handle_ptr(0);
16639  slider->show_buttons = nk_false;
16640  slider->bar_height = 8;
16641  slider->rounding = 0;
16642  slider->draw_begin = 0;
16643  slider->draw_end = 0;
16644 
16645  /* slider buttons */
16646  button = &style->slider.inc_button;
16647  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16648  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16649  button->active = nk_style_item_color(nk_rgb(44,44,44));
16650  button->border_color = nk_rgb(65,65,65);
16651  button->text_background = nk_rgb(40,40,40);
16652  button->text_normal = nk_rgb(175,175,175);
16653  button->text_hover = nk_rgb(175,175,175);
16654  button->text_active = nk_rgb(175,175,175);
16655  button->padding = nk_vec2(8.0f,8.0f);
16656  button->touch_padding = nk_vec2(0.0f,0.0f);
16657  button->userdata = nk_handle_ptr(0);
16658  button->text_alignment = NK_TEXT_CENTERED;
16659  button->border = 1.0f;
16660  button->rounding = 0.0f;
16661  button->draw_begin = 0;
16662  button->draw_end = 0;
16663  style->slider.dec_button = style->slider.inc_button;
16664 
16665  /* progressbar */
16666  prog = &style->progress;
16667  nk_zero_struct(*prog);
16668  prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]);
16669  prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]);
16670  prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]);
16674  prog->border_color = nk_rgba(0,0,0,0);
16675  prog->cursor_border_color = nk_rgba(0,0,0,0);
16676  prog->userdata = nk_handle_ptr(0);
16677  prog->padding = nk_vec2(4,4);
16678  prog->rounding = 0;
16679  prog->border = 0;
16680  prog->cursor_rounding = 0;
16681  prog->cursor_border = 0;
16682  prog->draw_begin = 0;
16683  prog->draw_end = 0;
16684 
16685  /* scrollbars */
16686  scroll = &style->scrollh;
16687  nk_zero_struct(*scroll);
16688  scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16689  scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16690  scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]);
16696  scroll->userdata = nk_handle_ptr(0);
16697  scroll->border_color = table[NK_COLOR_SCROLLBAR];
16698  scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR];
16699  scroll->padding = nk_vec2(0,0);
16700  scroll->show_buttons = nk_false;
16701  scroll->border = 0;
16702  scroll->rounding = 0;
16703  scroll->border_cursor = 0;
16704  scroll->rounding_cursor = 0;
16705  scroll->draw_begin = 0;
16706  scroll->draw_end = 0;
16707  style->scrollv = style->scrollh;
16708 
16709  /* scrollbars buttons */
16710  button = &style->scrollh.inc_button;
16711  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16712  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16713  button->active = nk_style_item_color(nk_rgb(44,44,44));
16714  button->border_color = nk_rgb(65,65,65);
16715  button->text_background = nk_rgb(40,40,40);
16716  button->text_normal = nk_rgb(175,175,175);
16717  button->text_hover = nk_rgb(175,175,175);
16718  button->text_active = nk_rgb(175,175,175);
16719  button->padding = nk_vec2(4.0f,4.0f);
16720  button->touch_padding = nk_vec2(0.0f,0.0f);
16721  button->userdata = nk_handle_ptr(0);
16722  button->text_alignment = NK_TEXT_CENTERED;
16723  button->border = 1.0f;
16724  button->rounding = 0.0f;
16725  button->draw_begin = 0;
16726  button->draw_end = 0;
16727  style->scrollh.dec_button = style->scrollh.inc_button;
16728  style->scrollv.inc_button = style->scrollh.inc_button;
16729  style->scrollv.dec_button = style->scrollh.inc_button;
16730 
16731  /* edit */
16732  edit = &style->edit;
16733  nk_zero_struct(*edit);
16734  edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]);
16735  edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]);
16736  edit->active = nk_style_item_color(table[NK_COLOR_EDIT]);
16737  edit->cursor_normal = table[NK_COLOR_TEXT];
16738  edit->cursor_hover = table[NK_COLOR_TEXT];
16739  edit->cursor_text_normal= table[NK_COLOR_EDIT];
16740  edit->cursor_text_hover = table[NK_COLOR_EDIT];
16741  edit->border_color = table[NK_COLOR_BORDER];
16742  edit->text_normal = table[NK_COLOR_TEXT];
16743  edit->text_hover = table[NK_COLOR_TEXT];
16744  edit->text_active = table[NK_COLOR_TEXT];
16745  edit->selected_normal = table[NK_COLOR_TEXT];
16746  edit->selected_hover = table[NK_COLOR_TEXT];
16747  edit->selected_text_normal = table[NK_COLOR_EDIT];
16748  edit->selected_text_hover = table[NK_COLOR_EDIT];
16749  edit->scrollbar_size = nk_vec2(10,10);
16750  edit->scrollbar = style->scrollv;
16751  edit->padding = nk_vec2(4,4);
16752  edit->row_padding = 2;
16753  edit->cursor_size = 4;
16754  edit->border = 1;
16755  edit->rounding = 0;
16756 
16757  /* property */
16758  property = &style->property;
16759  nk_zero_struct(*property);
16760  property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16761  property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16762  property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16763  property->border_color = table[NK_COLOR_BORDER];
16764  property->label_normal = table[NK_COLOR_TEXT];
16765  property->label_hover = table[NK_COLOR_TEXT];
16766  property->label_active = table[NK_COLOR_TEXT];
16767  property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
16768  property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
16769  property->userdata = nk_handle_ptr(0);
16770  property->padding = nk_vec2(4,4);
16771  property->border = 1;
16772  property->rounding = 10;
16773  property->draw_begin = 0;
16774  property->draw_end = 0;
16775 
16776  /* property buttons */
16777  button = &style->property.dec_button;
16778  nk_zero_struct(*button);
16779  button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16780  button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16781  button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16782  button->border_color = nk_rgba(0,0,0,0);
16783  button->text_background = table[NK_COLOR_PROPERTY];
16784  button->text_normal = table[NK_COLOR_TEXT];
16785  button->text_hover = table[NK_COLOR_TEXT];
16786  button->text_active = table[NK_COLOR_TEXT];
16787  button->padding = nk_vec2(0.0f,0.0f);
16788  button->touch_padding = nk_vec2(0.0f,0.0f);
16789  button->userdata = nk_handle_ptr(0);
16790  button->text_alignment = NK_TEXT_CENTERED;
16791  button->border = 0.0f;
16792  button->rounding = 0.0f;
16793  button->draw_begin = 0;
16794  button->draw_end = 0;
16795  style->property.inc_button = style->property.dec_button;
16796 
16797  /* property edit */
16798  edit = &style->property.edit;
16799  nk_zero_struct(*edit);
16803  edit->border_color = nk_rgba(0,0,0,0);
16804  edit->cursor_normal = table[NK_COLOR_TEXT];
16805  edit->cursor_hover = table[NK_COLOR_TEXT];
16806  edit->cursor_text_normal= table[NK_COLOR_EDIT];
16807  edit->cursor_text_hover = table[NK_COLOR_EDIT];
16808  edit->text_normal = table[NK_COLOR_TEXT];
16809  edit->text_hover = table[NK_COLOR_TEXT];
16810  edit->text_active = table[NK_COLOR_TEXT];
16811  edit->selected_normal = table[NK_COLOR_TEXT];
16812  edit->selected_hover = table[NK_COLOR_TEXT];
16813  edit->selected_text_normal = table[NK_COLOR_EDIT];
16814  edit->selected_text_hover = table[NK_COLOR_EDIT];
16815  edit->padding = nk_vec2(0,0);
16816  edit->cursor_size = 8;
16817  edit->border = 0;
16818  edit->rounding = 0;
16819 
16820  /* chart */
16821  chart = &style->chart;
16822  nk_zero_struct(*chart);
16824  chart->border_color = table[NK_COLOR_BORDER];
16826  chart->color = table[NK_COLOR_CHART_COLOR];
16827  chart->padding = nk_vec2(4,4);
16828  chart->border = 0;
16829  chart->rounding = 0;
16830 
16831  /* combo */
16832  combo = &style->combo;
16833  combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
16834  combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
16835  combo->active = nk_style_item_color(table[NK_COLOR_COMBO]);
16836  combo->border_color = table[NK_COLOR_BORDER];
16837  combo->label_normal = table[NK_COLOR_TEXT];
16838  combo->label_hover = table[NK_COLOR_TEXT];
16839  combo->label_active = table[NK_COLOR_TEXT];
16843  combo->content_padding = nk_vec2(4,4);
16844  combo->button_padding = nk_vec2(0,4);
16845  combo->spacing = nk_vec2(4,0);
16846  combo->border = 1;
16847  combo->rounding = 0;
16848 
16849  /* combo button */
16850  button = &style->combo.button;
16851  nk_zero_struct(*button);
16852  button->normal = nk_style_item_color(table[NK_COLOR_COMBO]);
16853  button->hover = nk_style_item_color(table[NK_COLOR_COMBO]);
16854  button->active = nk_style_item_color(table[NK_COLOR_COMBO]);
16855  button->border_color = nk_rgba(0,0,0,0);
16856  button->text_background = table[NK_COLOR_COMBO];
16857  button->text_normal = table[NK_COLOR_TEXT];
16858  button->text_hover = table[NK_COLOR_TEXT];
16859  button->text_active = table[NK_COLOR_TEXT];
16860  button->padding = nk_vec2(2.0f,2.0f);
16861  button->touch_padding = nk_vec2(0.0f,0.0f);
16862  button->userdata = nk_handle_ptr(0);
16863  button->text_alignment = NK_TEXT_CENTERED;
16864  button->border = 0.0f;
16865  button->rounding = 0.0f;
16866  button->draw_begin = 0;
16867  button->draw_end = 0;
16868 
16869  /* tab */
16870  tab = &style->tab;
16872  tab->border_color = table[NK_COLOR_BORDER];
16873  tab->text = table[NK_COLOR_TEXT];
16876  tab->padding = nk_vec2(4,4);
16877  tab->spacing = nk_vec2(4,4);
16878  tab->indent = 10.0f;
16879  tab->border = 1;
16880  tab->rounding = 0;
16881 
16882  /* tab button */
16883  button = &style->tab.tab_minimize_button;
16884  nk_zero_struct(*button);
16886  button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]);
16888  button->border_color = nk_rgba(0,0,0,0);
16889  button->text_background = table[NK_COLOR_TAB_HEADER];
16890  button->text_normal = table[NK_COLOR_TEXT];
16891  button->text_hover = table[NK_COLOR_TEXT];
16892  button->text_active = table[NK_COLOR_TEXT];
16893  button->padding = nk_vec2(2.0f,2.0f);
16894  button->touch_padding = nk_vec2(0.0f,0.0f);
16895  button->userdata = nk_handle_ptr(0);
16896  button->text_alignment = NK_TEXT_CENTERED;
16897  button->border = 0.0f;
16898  button->rounding = 0.0f;
16899  button->draw_begin = 0;
16900  button->draw_end = 0;
16901  style->tab.tab_maximize_button =*button;
16902 
16903  /* node button */
16904  button = &style->tab.node_minimize_button;
16905  nk_zero_struct(*button);
16906  button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]);
16907  button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]);
16908  button->active = nk_style_item_color(table[NK_COLOR_WINDOW]);
16909  button->border_color = nk_rgba(0,0,0,0);
16910  button->text_background = table[NK_COLOR_TAB_HEADER];
16911  button->text_normal = table[NK_COLOR_TEXT];
16912  button->text_hover = table[NK_COLOR_TEXT];
16913  button->text_active = table[NK_COLOR_TEXT];
16914  button->padding = nk_vec2(2.0f,2.0f);
16915  button->touch_padding = nk_vec2(0.0f,0.0f);
16916  button->userdata = nk_handle_ptr(0);
16917  button->text_alignment = NK_TEXT_CENTERED;
16918  button->border = 0.0f;
16919  button->rounding = 0.0f;
16920  button->draw_begin = 0;
16921  button->draw_end = 0;
16922  style->tab.node_maximize_button =*button;
16923 
16924  /* window header */
16925  win = &style->window;
16926  win->header.align = NK_HEADER_RIGHT;
16933  win->header.label_normal = table[NK_COLOR_TEXT];
16934  win->header.label_hover = table[NK_COLOR_TEXT];
16935  win->header.label_active = table[NK_COLOR_TEXT];
16936  win->header.label_padding = nk_vec2(4,4);
16937  win->header.padding = nk_vec2(4,4);
16938  win->header.spacing = nk_vec2(0,0);
16939 
16940  /* window header close button */
16941  button = &style->window.header.close_button;
16942  nk_zero_struct(*button);
16943  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16944  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16945  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
16946  button->border_color = nk_rgba(0,0,0,0);
16947  button->text_background = table[NK_COLOR_HEADER];
16948  button->text_normal = table[NK_COLOR_TEXT];
16949  button->text_hover = table[NK_COLOR_TEXT];
16950  button->text_active = table[NK_COLOR_TEXT];
16951  button->padding = nk_vec2(0.0f,0.0f);
16952  button->touch_padding = nk_vec2(0.0f,0.0f);
16953  button->userdata = nk_handle_ptr(0);
16954  button->text_alignment = NK_TEXT_CENTERED;
16955  button->border = 0.0f;
16956  button->rounding = 0.0f;
16957  button->draw_begin = 0;
16958  button->draw_end = 0;
16959 
16960  /* window header minimize button */
16961  button = &style->window.header.minimize_button;
16962  nk_zero_struct(*button);
16963  button->normal = nk_style_item_color(table[NK_COLOR_HEADER]);
16964  button->hover = nk_style_item_color(table[NK_COLOR_HEADER]);
16965  button->active = nk_style_item_color(table[NK_COLOR_HEADER]);
16966  button->border_color = nk_rgba(0,0,0,0);
16967  button->text_background = table[NK_COLOR_HEADER];
16968  button->text_normal = table[NK_COLOR_TEXT];
16969  button->text_hover = table[NK_COLOR_TEXT];
16970  button->text_active = table[NK_COLOR_TEXT];
16971  button->padding = nk_vec2(0.0f,0.0f);
16972  button->touch_padding = nk_vec2(0.0f,0.0f);
16973  button->userdata = nk_handle_ptr(0);
16974  button->text_alignment = NK_TEXT_CENTERED;
16975  button->border = 0.0f;
16976  button->rounding = 0.0f;
16977  button->draw_begin = 0;
16978  button->draw_end = 0;
16979 
16980  /* window */
16981  win->background = table[NK_COLOR_WINDOW];
16983  win->border_color = table[NK_COLOR_BORDER];
16984  win->popup_border_color = table[NK_COLOR_BORDER];
16985  win->combo_border_color = table[NK_COLOR_BORDER];
16987  win->menu_border_color = table[NK_COLOR_BORDER];
16988  win->group_border_color = table[NK_COLOR_BORDER];
16989  win->tooltip_border_color = table[NK_COLOR_BORDER];
16990  win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]);
16991 
16992  win->rounding = 0.0f;
16993  win->spacing = nk_vec2(4,4);
16994  win->scrollbar_size = nk_vec2(10,10);
16995  win->min_size = nk_vec2(64,64);
16996 
16997  win->combo_border = 1.0f;
16998  win->contextual_border = 1.0f;
16999  win->menu_border = 1.0f;
17000  win->group_border = 1.0f;
17001  win->tooltip_border = 1.0f;
17002  win->popup_border = 1.0f;
17003  win->border = 2.0f;
17004  win->min_row_height_padding = 8;
17005 
17006  win->padding = nk_vec2(4,4);
17007  win->group_padding = nk_vec2(4,4);
17008  win->popup_padding = nk_vec2(4,4);
17009  win->combo_padding = nk_vec2(4,4);
17010  win->contextual_padding = nk_vec2(4,4);
17011  win->menu_padding = nk_vec2(4,4);
17012  win->tooltip_padding = nk_vec2(4,4);
17013 }
17014 
17015 NK_API void
17016 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
17017 {
17018  struct nk_style *style;
17019  NK_ASSERT(ctx);
17020 
17021  if (!ctx) return;
17022  style = &ctx->style;
17023  style->font = font;
17024  ctx->stacks.fonts.head = 0;
17025  if (ctx->current)
17027 }
17028 
17029 NK_API int
17030 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
17031 {
17032  struct nk_config_stack_user_font *font_stack;
17033  struct nk_config_stack_user_font_element *element;
17034 
17035  NK_ASSERT(ctx);
17036  if (!ctx) return 0;
17037 
17038  font_stack = &ctx->stacks.fonts;
17039  NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
17040  if (font_stack->head >= (int)NK_LEN(font_stack->elements))
17041  return 0;
17042 
17043  element = &font_stack->elements[font_stack->head++];
17044  element->address = &ctx->style.font;
17045  element->old_value = ctx->style.font;
17046  ctx->style.font = font;
17047  return 1;
17048 }
17049 
17050 NK_API int
17051 nk_style_pop_font(struct nk_context *ctx)
17052 {
17053  struct nk_config_stack_user_font *font_stack;
17054  struct nk_config_stack_user_font_element *element;
17055 
17056  NK_ASSERT(ctx);
17057  if (!ctx) return 0;
17058 
17059  font_stack = &ctx->stacks.fonts;
17060  NK_ASSERT(font_stack->head > 0);
17061  if (font_stack->head < 1)
17062  return 0;
17063 
17064  element = &font_stack->elements[--font_stack->head];
17065  *element->address = element->old_value;
17066  return 1;
17067 }
17068 
17069 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
17070 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
17071 {\
17072  struct nk_config_stack_##type * type_stack;\
17073  struct nk_config_stack_##type##_element *element;\
17074  NK_ASSERT(ctx);\
17075  if (!ctx) return 0;\
17076  type_stack = &ctx->stacks.stack;\
17077  NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
17078  if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
17079  return 0;\
17080  element = &type_stack->elements[type_stack->head++];\
17081  element->address = address;\
17082  element->old_value = *address;\
17083  *address = value;\
17084  return 1;\
17085 }
17086 
17087 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
17088 nk_style_pop_##type(struct nk_context *ctx)\
17089 {\
17090  struct nk_config_stack_##type *type_stack;\
17091  struct nk_config_stack_##type##_element *element;\
17092  NK_ASSERT(ctx);\
17093  if (!ctx) return 0;\
17094  type_stack = &ctx->stacks.stack;\
17095  NK_ASSERT(type_stack->head > 0);\
17096  if (type_stack->head < 1)\
17097  return 0;\
17098  element = &type_stack->elements[--type_stack->head];\
17099  *element->address = element->old_value;\
17100  return 1;\
17101 }
17102 
17103 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
17104 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
17105 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
17106 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
17107 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
17108 
17109 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
17110 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
17111 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
17112 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
17113 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
17114 
17115 NK_API int
17116 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c)
17117 {
17118  struct nk_style *style;
17119  NK_ASSERT(ctx);
17120  if (!ctx) return 0;
17121  style = &ctx->style;
17122  if (style->cursors[c]) {
17123  style->cursor_active = style->cursors[c];
17124  return 1;
17125  }
17126  return 0;
17127 }
17128 
17129 NK_API void
17130 nk_style_show_cursor(struct nk_context *ctx)
17131 {
17132  ctx->style.cursor_visible = nk_true;
17133 }
17134 
17135 NK_API void
17136 nk_style_hide_cursor(struct nk_context *ctx)
17137 {
17138  ctx->style.cursor_visible = nk_false;
17139 }
17140 
17141 NK_API void
17142 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
17143  const struct nk_cursor *c)
17144 {
17145  struct nk_style *style;
17146  NK_ASSERT(ctx);
17147  if (!ctx) return;
17148  style = &ctx->style;
17149  style->cursors[cursor] = c;
17150 }
17151 
17152 NK_API void
17153 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors)
17154 {
17155  int i = 0;
17156  struct nk_style *style;
17157  NK_ASSERT(ctx);
17158  if (!ctx) return;
17159  style = &ctx->style;
17160  for (i = 0; i < NK_CURSOR_COUNT; ++i)
17161  style->cursors[i] = &cursors[i];
17162  style->cursor_visible = nk_true;
17163 }
17164 
17165 /* ===============================================================
17166  *
17167  * POOL
17168  *
17169  * ===============================================================*/
17170 NK_INTERN void
17171 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
17172  unsigned int capacity)
17173 {
17174  nk_zero(pool, sizeof(*pool));
17175  pool->alloc = *alloc;
17176  pool->capacity = capacity;
17177  pool->type = NK_BUFFER_DYNAMIC;
17178  pool->pages = 0;
17179 }
17180 
17181 NK_INTERN void
17182 nk_pool_free(struct nk_pool *pool)
17183 {
17184  struct nk_page *iter = pool->pages;
17185  if (!pool) return;
17186  if (pool->type == NK_BUFFER_FIXED) return;
17187  while (iter) {
17188  struct nk_page *next = iter->next;
17189  pool->alloc.free(pool->alloc.userdata, iter);
17190  iter = next;
17191  }
17192 }
17193 
17194 NK_INTERN void
17195 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
17196 {
17197  nk_zero(pool, sizeof(*pool));
17198  NK_ASSERT(size >= sizeof(struct nk_page));
17199  if (size < sizeof(struct nk_page)) return;
17200  pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
17201  pool->pages = (struct nk_page*)memory;
17202  pool->type = NK_BUFFER_FIXED;
17203  pool->size = size;
17204 }
17205 
17206 NK_INTERN struct nk_page_element*
17207 nk_pool_alloc(struct nk_pool *pool)
17208 {
17209  if (!pool->pages || pool->pages->size >= pool->capacity) {
17210  /* allocate new page */
17211  struct nk_page *page;
17212  if (pool->type == NK_BUFFER_FIXED) {
17213  if (!pool->pages) {
17214  NK_ASSERT(pool->pages);
17215  return 0;
17216  }
17217  NK_ASSERT(pool->pages->size < pool->capacity);
17218  return 0;
17219  } else {
17220  nk_size size = sizeof(struct nk_page);
17221  size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
17222  page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
17223  page->next = pool->pages;
17224  pool->pages = page;
17225  page->size = 0;
17226  }
17227  }
17228  return &pool->pages->win[pool->pages->size++];
17229 }
17230 
17231 /* ===============================================================
17232  *
17233  * CONTEXT
17234  *
17235  * ===============================================================*/
17236 NK_INTERN void* nk_create_window(struct nk_context *ctx);
17237 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*);
17238 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win);
17239 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
17240 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
17241 NK_INTERN void* nk_create_panel(struct nk_context *ctx);
17242 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan);
17243 
17244 NK_INTERN void
17245 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
17246 {
17247  NK_ASSERT(ctx);
17248  if (!ctx) return;
17249  nk_zero_struct(*ctx);
17250  nk_style_default(ctx);
17251  ctx->seq = 1;
17252  if (font) ctx->style.font = font;
17253 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17254  nk_draw_list_init(&ctx->draw_list);
17255 #endif
17256 }
17257 
17258 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
17259 NK_API int
17260 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
17261 {
17262  struct nk_allocator alloc;
17263  alloc.userdata.ptr = 0;
17264  alloc.alloc = nk_malloc;
17265  alloc.free = nk_mfree;
17266  return nk_init(ctx, &alloc, font);
17267 }
17268 #endif
17269 
17270 NK_API int
17271 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
17272  const struct nk_user_font *font)
17273 {
17274  NK_ASSERT(memory);
17275  if (!memory) return 0;
17276  nk_setup(ctx, font);
17277  nk_buffer_init_fixed(&ctx->memory, memory, size);
17278  ctx->use_pool = nk_false;
17279  return 1;
17280 }
17281 
17282 NK_API int
17283 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
17284  struct nk_buffer *pool, const struct nk_user_font *font)
17285 {
17286  NK_ASSERT(cmds);
17287  NK_ASSERT(pool);
17288  if (!cmds || !pool) return 0;
17289 
17290  nk_setup(ctx, font);
17291  ctx->memory = *cmds;
17292  if (pool->type == NK_BUFFER_FIXED) {
17293  /* take memory from buffer and alloc fixed pool */
17294  nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
17295  } else {
17296  /* create dynamic pool from buffer allocator */
17297  struct nk_allocator *alloc = &pool->pool;
17298  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17299  }
17300  ctx->use_pool = nk_true;
17301  return 1;
17302 }
17303 
17304 NK_API int
17305 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
17306  const struct nk_user_font *font)
17307 {
17308  NK_ASSERT(alloc);
17309  if (!alloc) return 0;
17310  nk_setup(ctx, font);
17311  nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
17312  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17313  ctx->use_pool = nk_true;
17314  return 1;
17315 }
17316 
17317 #ifdef NK_INCLUDE_COMMAND_USERDATA
17318 NK_API void
17319 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
17320 {
17321  if (!ctx) return;
17322  ctx->userdata = handle;
17323  if (ctx->current)
17324  ctx->current->buffer.userdata = handle;
17325 }
17326 #endif
17327 
17328 NK_API void
17329 nk_free(struct nk_context *ctx)
17330 {
17331  NK_ASSERT(ctx);
17332  if (!ctx) return;
17333  nk_buffer_free(&ctx->memory);
17334  if (ctx->use_pool)
17335  nk_pool_free(&ctx->pool);
17336 
17337  nk_zero(&ctx->input, sizeof(ctx->input));
17338  nk_zero(&ctx->style, sizeof(ctx->style));
17339  nk_zero(&ctx->memory, sizeof(ctx->memory));
17340 
17341  ctx->seq = 0;
17342  ctx->build = 0;
17343  ctx->begin = 0;
17344  ctx->end = 0;
17345  ctx->active = 0;
17346  ctx->current = 0;
17347  ctx->freelist = 0;
17348  ctx->count = 0;
17349 }
17350 
17351 NK_API void
17352 nk_clear(struct nk_context *ctx)
17353 {
17354  struct nk_window *iter;
17355  struct nk_window *next;
17356  NK_ASSERT(ctx);
17357 
17358  if (!ctx) return;
17359  if (ctx->use_pool)
17360  nk_buffer_clear(&ctx->memory);
17361  else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
17362 
17363  ctx->build = 0;
17364  ctx->memory.calls = 0;
17365  ctx->last_widget_state = 0;
17367  NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
17368 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17369  nk_draw_list_clear(&ctx->draw_list);
17370 #endif
17371 
17372  /* garbage collector */
17373  iter = ctx->begin;
17374  while (iter) {
17375  /* make sure minimized windows do not get removed */
17376  if ((iter->flags & NK_WINDOW_MINIMIZED) &&
17377  !(iter->flags & NK_WINDOW_CLOSED)) {
17378  iter = iter->next;
17379  continue;
17380  }
17381  /* remove hotness from hidden or closed windows*/
17382  if (((iter->flags & NK_WINDOW_HIDDEN) ||
17383  (iter->flags & NK_WINDOW_CLOSED)) &&
17384  iter == ctx->active)
17385  ctx->active = iter->next;
17386 
17387  /* free unused popup windows */
17388  if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
17389  nk_free_window(ctx, iter->popup.win);
17390  iter->popup.win = 0;
17391  }
17392  /* remove unused window state tables */
17393  {struct nk_table *n, *it = iter->tables;
17394  while (it) {
17395  n = it->next;
17396  if (it->seq != ctx->seq) {
17397  nk_remove_table(iter, it);
17398  nk_zero(it, sizeof(union nk_page_data));
17399  nk_free_table(ctx, it);
17400  if (it == iter->tables)
17401  iter->tables = n;
17402  }
17403  it = n;
17404  }}
17405  /* window itself is not used anymore so free */
17406  if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
17407  next = iter->next;
17408  nk_remove_window(ctx, iter);
17409  nk_free_window(ctx, iter);
17410  iter = next;
17411  } else iter = iter->next;
17412  }
17413  ctx->seq++;
17414 }
17415 
17416 /* ----------------------------------------------------------------
17417  *
17418  * BUFFERING
17419  *
17420  * ---------------------------------------------------------------*/
17421 NK_INTERN void
17422 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17423 {
17424  NK_ASSERT(ctx);
17425  NK_ASSERT(buffer);
17426  if (!ctx || !buffer) return;
17427  buffer->begin = ctx->memory.allocated;
17428  buffer->end = buffer->begin;
17429  buffer->last = buffer->begin;
17430  buffer->clip = nk_null_rect;
17431 }
17432 
17433 NK_INTERN void
17434 nk_start(struct nk_context *ctx, struct nk_window *win)
17435 {
17436  NK_ASSERT(ctx);
17437  NK_ASSERT(win);
17438  nk_start_buffer(ctx, &win->buffer);
17439 }
17440 
17441 NK_INTERN void
17442 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
17443 {
17444  struct nk_popup_buffer *buf;
17445  NK_ASSERT(ctx);
17446  NK_ASSERT(win);
17447  if (!ctx || !win) return;
17448 
17449  /* save buffer fill state for popup */
17450  buf = &win->popup.buf;
17451  buf->begin = win->buffer.end;
17452  buf->end = win->buffer.end;
17453  buf->parent = win->buffer.last;
17454  buf->last = buf->begin;
17455  buf->active = nk_true;
17456 }
17457 
17458 NK_INTERN void
17459 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
17460 {
17461  struct nk_popup_buffer *buf;
17462  NK_ASSERT(ctx);
17463  NK_ASSERT(win);
17464  if (!ctx || !win) return;
17465 
17466  buf = &win->popup.buf;
17467  buf->last = win->buffer.last;
17468  buf->end = win->buffer.end;
17469 }
17470 
17471 NK_INTERN void
17472 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17473 {
17474  NK_ASSERT(ctx);
17475  NK_ASSERT(buffer);
17476  if (!ctx || !buffer) return;
17477  buffer->end = ctx->memory.allocated;
17478 }
17479 
17480 NK_INTERN void
17481 nk_finish(struct nk_context *ctx, struct nk_window *win)
17482 {
17483  struct nk_popup_buffer *buf;
17484  struct nk_command *parent_last;
17485  void *memory;
17486 
17487  NK_ASSERT(ctx);
17488  NK_ASSERT(win);
17489  if (!ctx || !win) return;
17490  nk_finish_buffer(ctx, &win->buffer);
17491  if (!win->popup.buf.active) return;
17492 
17493  buf = &win->popup.buf;
17494  memory = ctx->memory.memory.ptr;
17495  parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
17496  parent_last->next = buf->end;
17497 }
17498 
17499 NK_INTERN void
17500 nk_build(struct nk_context *ctx)
17501 {
17502  struct nk_window *iter = 0;
17503  struct nk_command *cmd = 0;
17504  nk_byte *buffer = 0;
17505 
17506  /* draw cursor overlay */
17507  if (!ctx->style.cursor_active)
17509  if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
17510  struct nk_rect mouse_bounds;
17511  const struct nk_cursor *cursor = ctx->style.cursor_active;
17512  nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
17513  nk_start_buffer(ctx, &ctx->overlay);
17514 
17515  mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
17516  mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
17517  mouse_bounds.w = cursor->size.x;
17518  mouse_bounds.h = cursor->size.y;
17519 
17520  nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
17521  nk_finish_buffer(ctx, &ctx->overlay);
17522  }
17523  /* build one big draw command list out of all window buffers */
17524  iter = ctx->begin;
17525  buffer = (nk_byte*)ctx->memory.memory.ptr;
17526  while (iter != 0) {
17527  struct nk_window *next = iter->next;
17528  if (iter->buffer.last == iter->buffer.begin || (iter->flags & NK_WINDOW_HIDDEN)||
17529  iter->seq != ctx->seq)
17530  goto cont;
17531 
17532  cmd = nk_ptr_add(struct nk_command, buffer, iter->buffer.last);
17533  while (next && ((next->buffer.last == next->buffer.begin) ||
17534  (next->flags & NK_WINDOW_HIDDEN)))
17535  next = next->next; /* skip empty command buffers */
17536 
17537  if (next) cmd->next = next->buffer.begin;
17538  cont: iter = next;
17539  }
17540  /* append all popup draw commands into lists */
17541  iter = ctx->begin;
17542  while (iter != 0) {
17543  struct nk_window *next = iter->next;
17544  struct nk_popup_buffer *buf;
17545  if (!iter->popup.buf.active)
17546  goto skip;
17547 
17548  buf = &iter->popup.buf;
17549  cmd->next = buf->begin;
17550  cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
17551  buf->active = nk_false;
17552  skip: iter = next;
17553  }
17554  /* append overlay commands */
17555  if (cmd) {
17556  if (ctx->overlay.end != ctx->overlay.begin)
17557  cmd->next = ctx->overlay.begin;
17558  else cmd->next = ctx->memory.allocated;
17559  }
17560 }
17561 
17562 NK_API const struct nk_command*
17563 nk__begin(struct nk_context *ctx)
17564 {
17565  struct nk_window *iter;
17566  nk_byte *buffer;
17567  NK_ASSERT(ctx);
17568  if (!ctx) return 0;
17569  if (!ctx->count) return 0;
17570 
17571  buffer = (nk_byte*)ctx->memory.memory.ptr;
17572  if (!ctx->build) {
17573  nk_build(ctx);
17574  ctx->build = nk_true;
17575  }
17576  iter = ctx->begin;
17577  while (iter && ((iter->buffer.begin == iter->buffer.end) || (iter->flags & NK_WINDOW_HIDDEN)))
17578  iter = iter->next;
17579  if (!iter) return 0;
17580  return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
17581 }
17582 
17583 NK_API const struct nk_command*
17584 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
17585 {
17586  nk_byte *buffer;
17587  const struct nk_command *next;
17588  NK_ASSERT(ctx);
17589  if (!ctx || !cmd || !ctx->count) return 0;
17590  if (cmd->next >= ctx->memory.allocated) return 0;
17591  buffer = (nk_byte*)ctx->memory.memory.ptr;
17592  next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
17593  return next;
17594 }
17595 
17596 /* ----------------------------------------------------------------
17597  *
17598  * PANEL
17599  *
17600  * ---------------------------------------------------------------*/
17601 static int
17602 nk_panel_has_header(nk_flags flags, const char *title)
17603 {
17604  int active = 0;
17605  active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE));
17606  active = active || (flags & NK_WINDOW_TITLE);
17607  active = active && !(flags & NK_WINDOW_HIDDEN) && title;
17608  return active;
17609 }
17610 
17611 NK_INTERN struct nk_vec2
17612 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
17613 {
17614  switch (type) {
17615  default:
17616  case NK_PANEL_WINDOW: return style->window.padding;
17617  case NK_PANEL_GROUP: return style->window.group_padding;
17618  case NK_PANEL_POPUP: return style->window.popup_padding;
17619  case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
17620  case NK_PANEL_COMBO: return style->window.combo_padding;
17621  case NK_PANEL_MENU: return style->window.menu_padding;
17622  case NK_PANEL_TOOLTIP: return style->window.menu_padding;
17623  }
17624 }
17625 
17626 NK_INTERN float
17627 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
17628  enum nk_panel_type type)
17629 {
17630  if (flags & NK_WINDOW_BORDER) {
17631  switch (type) {
17632  default:
17633  case NK_PANEL_WINDOW: return style->window.border;
17634  case NK_PANEL_GROUP: return style->window.group_border;
17635  case NK_PANEL_POPUP: return style->window.popup_border;
17636  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
17637  case NK_PANEL_COMBO: return style->window.combo_border;
17638  case NK_PANEL_MENU: return style->window.menu_border;
17639  case NK_PANEL_TOOLTIP: return style->window.menu_border;
17640  }} else return 0;
17641 }
17642 
17643 NK_INTERN struct nk_color
17644 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
17645 {
17646  switch (type) {
17647  default:
17648  case NK_PANEL_WINDOW: return style->window.border_color;
17649  case NK_PANEL_GROUP: return style->window.group_border_color;
17650  case NK_PANEL_POPUP: return style->window.popup_border_color;
17651  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
17652  case NK_PANEL_COMBO: return style->window.combo_border_color;
17653  case NK_PANEL_MENU: return style->window.menu_border_color;
17654  case NK_PANEL_TOOLTIP: return style->window.menu_border_color;
17655  }
17656 }
17657 
17658 NK_INTERN int
17659 nk_panel_is_sub(enum nk_panel_type type)
17660 {
17661  return (type & NK_PANEL_SET_SUB)?1:0;
17662 }
17663 
17664 NK_INTERN int
17665 nk_panel_is_nonblock(enum nk_panel_type type)
17666 {
17667  return (type & NK_PANEL_SET_NONBLOCK)?1:0;
17668 }
17669 
17670 NK_INTERN int
17671 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
17672 {
17673  struct nk_input *in;
17674  struct nk_window *win;
17675  struct nk_panel *layout;
17676  struct nk_command_buffer *out;
17677  const struct nk_style *style;
17678  const struct nk_user_font *font;
17679 
17680  struct nk_vec2 scrollbar_size;
17681  struct nk_vec2 panel_padding;
17682 
17683  NK_ASSERT(ctx);
17684  NK_ASSERT(ctx->current);
17685  NK_ASSERT(ctx->current->layout);
17686  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17687  nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
17688  if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
17689  nk_zero(ctx->current->layout, sizeof(struct nk_panel));
17690  ctx->current->layout->type = panel_type;
17691  return 0;
17692  }
17693  /* pull state into local stack */
17694  style = &ctx->style;
17695  font = style->font;
17696  win = ctx->current;
17697  layout = win->layout;
17698  out = &win->buffer;
17699  in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
17701  win->buffer.userdata = ctx->userdata;
17702 #endif
17703  /* pull style configuration into local stack */
17704  scrollbar_size = style->window.scrollbar_size;
17705  panel_padding = nk_panel_get_padding(style, panel_type);
17706 
17707  /* window movement */
17708  if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
17709  int left_mouse_down;
17710  int left_mouse_click_in_cursor;
17711 
17712  /* calculate draggable window space */
17713  struct nk_rect header;
17714  header.x = win->bounds.x;
17715  header.y = win->bounds.y;
17716  header.w = win->bounds.w;
17717  if (nk_panel_has_header(win->flags, title)) {
17718  header.h = font->height + 2.0f * style->window.header.padding.y;
17719  header.h += 2.0f * style->window.header.label_padding.y;
17720  } else header.h = panel_padding.y;
17721 
17722  /* window movement by dragging */
17723  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17724  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
17725  NK_BUTTON_LEFT, header, nk_true);
17726  if (left_mouse_down && left_mouse_click_in_cursor) {
17727  win->bounds.x = win->bounds.x + in->mouse.delta.x;
17728  win->bounds.y = win->bounds.y + in->mouse.delta.y;
17732  }
17733  }
17734 
17735  /* setup panel */
17736  layout->type = panel_type;
17737  layout->flags = win->flags;
17738  layout->bounds = win->bounds;
17739  layout->bounds.x += panel_padding.x;
17740  layout->bounds.w -= 2*panel_padding.x;
17741  if (win->flags & NK_WINDOW_BORDER) {
17742  layout->border = nk_panel_get_border(style, win->flags, panel_type);
17743  layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
17744  } else layout->border = 0;
17745  layout->at_y = layout->bounds.y;
17746  layout->at_x = layout->bounds.x;
17747  layout->max_x = 0;
17748  layout->header_height = 0;
17749  layout->footer_height = 0;
17751  layout->row.index = 0;
17752  layout->row.columns = 0;
17753  layout->row.ratio = 0;
17754  layout->row.item_width = 0;
17755  layout->row.tree_depth = 0;
17756  layout->row.height = panel_padding.y;
17757  layout->has_scrolling = nk_true;
17758  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
17759  layout->bounds.w -= scrollbar_size.x;
17760  if (!nk_panel_is_nonblock(panel_type)) {
17761  layout->footer_height = 0;
17762  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
17763  layout->footer_height = scrollbar_size.y;
17764  layout->bounds.h -= layout->footer_height;
17765  }
17766 
17767  /* panel header */
17768  if (nk_panel_has_header(win->flags, title))
17769  {
17770  struct nk_text text;
17771  struct nk_rect header;
17772  const struct nk_style_item *background = 0;
17773 
17774  /* calculate header bounds */
17775  header.x = win->bounds.x;
17776  header.y = win->bounds.y;
17777  header.w = win->bounds.w;
17778  header.h = font->height + 2.0f * style->window.header.padding.y;
17779  header.h += (2.0f * style->window.header.label_padding.y);
17780 
17781  /* shrink panel by header */
17782  layout->header_height = header.h;
17783  layout->bounds.y += header.h;
17784  layout->bounds.h -= header.h;
17785  layout->at_y += header.h;
17786 
17787  /* select correct header background and text color */
17788  if (ctx->active == win) {
17789  background = &style->window.header.active;
17790  text.text = style->window.header.label_active;
17791  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
17792  background = &style->window.header.hover;
17793  text.text = style->window.header.label_hover;
17794  } else {
17795  background = &style->window.header.normal;
17796  text.text = style->window.header.label_normal;
17797  }
17798 
17799  /* draw header background */
17800  header.h += 1.0f;
17801  if (background->type == NK_STYLE_ITEM_IMAGE) {
17802  text.background = nk_rgba(0,0,0,0);
17803  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
17804  } else {
17805  text.background = background->data.color;
17806  nk_fill_rect(out, header, 0, background->data.color);
17807  }
17808 
17809  /* window close button */
17810  {struct nk_rect button;
17811  button.y = header.y + style->window.header.padding.y;
17812  button.h = header.h - 2 * style->window.header.padding.y;
17813  button.w = button.h;
17814  if (win->flags & NK_WINDOW_CLOSABLE) {
17815  nk_flags ws = 0;
17816  if (style->window.header.align == NK_HEADER_RIGHT) {
17817  button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
17818  header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
17819  } else {
17820  button.x = header.x + style->window.header.padding.x;
17821  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17822  }
17823 
17824  if (nk_do_button_symbol(&ws, &win->buffer, button,
17826  &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17827  {
17828  layout->flags |= NK_WINDOW_HIDDEN;
17829  layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
17830  }
17831  }
17832 
17833  /* window minimize button */
17834  if (win->flags & NK_WINDOW_MINIMIZABLE) {
17835  nk_flags ws = 0;
17836  if (style->window.header.align == NK_HEADER_RIGHT) {
17837  button.x = (header.w + header.x) - button.w;
17838  if (!(win->flags & NK_WINDOW_CLOSABLE)) {
17839  button.x -= style->window.header.padding.x;
17840  header.w -= style->window.header.padding.x;
17841  }
17842  header.w -= button.w + style->window.header.spacing.x;
17843  } else {
17844  button.x = header.x;
17845  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17846  }
17847  if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
17849  NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17850  layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
17851  layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
17852  layout->flags | NK_WINDOW_MINIMIZED;
17853  }}
17854 
17855  {/* window header title */
17856  int text_len = nk_strlen(title);
17857  struct nk_rect label = {0,0,0,0};
17858  float t = font->width(font->userdata, font->height, title, text_len);
17859  text.padding = nk_vec2(0,0);
17860 
17861  label.x = header.x + style->window.header.padding.x;
17862  label.x += style->window.header.label_padding.x;
17863  label.y = header.y + style->window.header.label_padding.y;
17864  label.h = font->height + 2 * style->window.header.label_padding.y;
17865  label.w = t + 2 * style->window.header.spacing.x;
17866  label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
17867  nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
17868  }
17869 
17870  /* draw window background */
17871  if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
17872  struct nk_rect body;
17873  body.x = win->bounds.x;
17874  body.w = win->bounds.w;
17875  body.y = (win->bounds.y + layout->header_height);
17876  body.h = (win->bounds.h - layout->header_height);
17878  nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
17879  else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color);
17880  }
17881 
17882  /* set clipping rectangle */
17883  {struct nk_rect clip;
17884  layout->clip = layout->bounds;
17885  nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
17886  layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
17887  nk_push_scissor(out, clip);
17888  layout->clip = clip;}
17889  return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
17890 }
17891 
17892 NK_INTERN void
17893 nk_panel_end(struct nk_context *ctx)
17894 {
17895  struct nk_input *in;
17896  struct nk_window *window;
17897  struct nk_panel *layout;
17898  const struct nk_style *style;
17899  struct nk_command_buffer *out;
17900 
17901  struct nk_vec2 scrollbar_size;
17902  struct nk_vec2 panel_padding;
17903 
17904  NK_ASSERT(ctx);
17905  NK_ASSERT(ctx->current);
17906  NK_ASSERT(ctx->current->layout);
17907  if (!ctx || !ctx->current || !ctx->current->layout)
17908  return;
17909 
17910  window = ctx->current;
17911  layout = window->layout;
17912  style = &ctx->style;
17913  out = &window->buffer;
17914  in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
17915  if (!nk_panel_is_sub(layout->type))
17916  nk_push_scissor(out, nk_null_rect);
17917 
17918  /* cache configuration data */
17919  scrollbar_size = style->window.scrollbar_size;
17920  panel_padding = nk_panel_get_padding(style, layout->type);
17921 
17922  /* update the current cursor Y-position to point over the last added widget */
17923  layout->at_y += layout->row.height;
17924 
17925  /* dynamic panels */
17926  if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
17927  {
17928  /* update panel height to fit dynamic growth */
17929  struct nk_rect empty_space;
17930  if (layout->at_y < (layout->bounds.y + layout->bounds.h))
17931  layout->bounds.h = layout->at_y - layout->bounds.y;
17932 
17933  /* fill top empty space */
17934  empty_space.x = window->bounds.x;
17935  empty_space.y = layout->bounds.y;
17936  empty_space.h = panel_padding.y;
17937  empty_space.w = window->bounds.w;
17938  nk_fill_rect(out, empty_space, 0, style->window.background);
17939 
17940  /* fill left empty space */
17941  empty_space.x = window->bounds.x;
17942  empty_space.y = layout->bounds.y;
17943  empty_space.w = panel_padding.x + layout->border;
17944  empty_space.h = layout->bounds.h;
17945  nk_fill_rect(out, empty_space, 0, style->window.background);
17946 
17947  /* fill right empty space */
17948  empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
17949  empty_space.y = layout->bounds.y;
17950  empty_space.w = panel_padding.x + layout->border;
17951  empty_space.h = layout->bounds.h;
17952  if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
17953  empty_space.w += scrollbar_size.x;
17954  nk_fill_rect(out, empty_space, 0, style->window.background);
17955 
17956  /* fill bottom empty space */
17957  if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
17958  empty_space.x = window->bounds.x;
17959  empty_space.y = layout->bounds.y + layout->bounds.h;
17960  empty_space.w = window->bounds.w;
17961  empty_space.h = scrollbar_size.y;
17962  nk_fill_rect(out, empty_space, 0, style->window.background);
17963  }
17964  }
17965 
17966  /* scrollbars */
17967  if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
17968  !(layout->flags & NK_WINDOW_MINIMIZED) &&
17970  {
17971  struct nk_rect scroll;
17972  int scroll_has_scrolling;
17973  float scroll_target;
17974  float scroll_offset;
17975  float scroll_step;
17976  float scroll_inc;
17977 
17978  /* mouse wheel scrolling */
17979  if (nk_panel_is_sub(layout->type))
17980  {
17981  /* sub-window mouse wheel scrolling */
17982  struct nk_window *root_window = window;
17983  struct nk_panel *root_panel = window->layout;
17984  while (root_panel->parent)
17985  root_panel = root_panel->parent;
17986  while (root_window->parent)
17987  root_window = root_window->parent;
17988 
17989  /* only allow scrolling if parent window is active */
17990  scroll_has_scrolling = 0;
17991  if ((root_window == ctx->active) && layout->has_scrolling) {
17992  /* and panel is being hovered and inside clip rect*/
17993  if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
17994  NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
17995  root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
17996  {
17997  /* deactivate all parent scrolling */
17998  root_panel = window->layout;
17999  while (root_panel->parent) {
18000  root_panel->has_scrolling = nk_false;
18001  root_panel = root_panel->parent;
18002  }
18003  root_panel->has_scrolling = nk_false;
18004  scroll_has_scrolling = nk_true;
18005  }
18006  }
18007  } else if (!nk_panel_is_sub(layout->type)) {
18008  /* window mouse wheel scrolling */
18009  scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
18010  if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
18011  window->scrolled = nk_true;
18012  else window->scrolled = nk_false;
18013  } else scroll_has_scrolling = nk_false;
18014 
18015  {
18016  /* vertical scrollbar */
18017  nk_flags state = 0;
18018  scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
18019  scroll.y = layout->bounds.y;
18020  scroll.w = scrollbar_size.x;
18021  scroll.h = layout->bounds.h;
18022 
18023  scroll_offset = (float)*layout->offset_y;
18024  scroll_step = scroll.h * 0.10f;
18025  scroll_inc = scroll.h * 0.01f;
18026  scroll_target = (float)(int)(layout->at_y - scroll.y);
18027  scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
18028  scroll_offset, scroll_target, scroll_step, scroll_inc,
18029  &ctx->style.scrollv, in, style->font);
18030  *layout->offset_y = (nk_uint)scroll_offset;
18031  if (in && scroll_has_scrolling)
18032  in->mouse.scroll_delta.y = 0;
18033  }
18034  {
18035  /* horizontal scrollbar */
18036  nk_flags state = 0;
18037  scroll.x = layout->bounds.x;
18038  scroll.y = layout->bounds.y + layout->bounds.h;
18039  scroll.w = layout->bounds.w;
18040  scroll.h = scrollbar_size.y;
18041 
18042  scroll_offset = (float)*layout->offset_x;
18043  scroll_target = (float)(int)(layout->max_x - scroll.x);
18044  scroll_step = layout->max_x * 0.05f;
18045  scroll_inc = layout->max_x * 0.005f;
18046  scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
18047  scroll_offset, scroll_target, scroll_step, scroll_inc,
18048  &ctx->style.scrollh, in, style->font);
18049  *layout->offset_x = (nk_uint)scroll_offset;
18050  }
18051  }
18052 
18053  /* hide scroll if no user input */
18054  if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
18055  int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
18056  int is_window_hovered = nk_window_is_hovered(ctx);
18057  int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18058  if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
18060  else window->scrollbar_hiding_timer = 0;
18061  } else window->scrollbar_hiding_timer = 0;
18062 
18063  /* window border */
18064  if (layout->flags & NK_WINDOW_BORDER)
18065  {
18066  struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
18067  const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ?
18068  style->window.border + window->bounds.y + layout->header_height:
18069  (layout->flags & NK_WINDOW_DYNAMIC)?
18070  layout->bounds.y + layout->bounds.h + layout->footer_height:
18071  window->bounds.y + window->bounds.h;
18072 
18073  /* draw border top */
18074  nk_stroke_line(out,window->bounds.x,window->bounds.y,
18075  window->bounds.x + window->bounds.w, window->bounds.y,
18076  layout->border, border_color);
18077 
18078  /* draw bottom border */
18079  nk_stroke_line(out, window->bounds.x, padding_y,
18080  window->bounds.x + window->bounds.w, padding_y, layout->border, border_color);
18081 
18082  /* draw left border */
18083  nk_stroke_line(out, window->bounds.x + layout->border*0.5f,
18084  window->bounds.y, window->bounds.x + layout->border*0.5f,
18085  padding_y, layout->border, border_color);
18086 
18087  /* draw right border */
18088  nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f,
18089  window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f,
18090  padding_y, layout->border, border_color);
18091  }
18092 
18093  /* scaler */
18094  if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
18095  {
18096  /* calculate scaler bounds */
18097  struct nk_rect scaler;
18098  scaler.w = scrollbar_size.x;
18099  scaler.h = scrollbar_size.y;
18100  scaler.y = layout->bounds.y + layout->bounds.h;
18101  if (layout->flags & NK_WINDOW_SCALE_LEFT)
18102  scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
18103  else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
18104  if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
18105  scaler.x -= scaler.w;
18106 
18107  /* draw scaler */
18108  {const struct nk_style_item *item = &style->window.scaler;
18109  if (item->type == NK_STYLE_ITEM_IMAGE)
18110  nk_draw_image(out, scaler, &item->data.image, nk_white);
18111  else {
18112  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
18113  nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
18114  scaler.y + scaler.h, scaler.x + scaler.w,
18115  scaler.y + scaler.h, item->data.color);
18116  } else {
18117  nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
18118  scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
18119  }
18120  }}
18121 
18122  /* do window scaling */
18123  if (!(window->flags & NK_WINDOW_ROM)) {
18124  struct nk_vec2 window_size = style->window.min_size;
18125  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
18126  int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
18127  NK_BUTTON_LEFT, scaler, nk_true);
18128 
18129  if (left_mouse_down && left_mouse_click_in_scaler) {
18130  float delta_x = in->mouse.delta.x;
18131  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
18132  delta_x = -delta_x;
18133  window->bounds.x += in->mouse.delta.x;
18134  }
18135  /* dragging in x-direction */
18136  if (window->bounds.w + delta_x >= window_size.x) {
18137  if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
18138  window->bounds.w = window->bounds.w + delta_x;
18139  scaler.x += in->mouse.delta.x;
18140  }
18141  }
18142  /* dragging in y-direction (only possible if static window) */
18143  if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
18144  if (window_size.y < window->bounds.h + in->mouse.delta.y) {
18145  if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
18146  window->bounds.h = window->bounds.h + in->mouse.delta.y;
18147  scaler.y += in->mouse.delta.y;
18148  }
18149  }
18150  }
18152  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
18153  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
18154  }
18155  }
18156  }
18157  if (!nk_panel_is_sub(layout->type)) {
18158  /* window is hidden so clear command buffer */
18159  if (layout->flags & NK_WINDOW_HIDDEN)
18160  nk_command_buffer_reset(&window->buffer);
18161  /* window is visible and not tab */
18162  else nk_finish(ctx, window);
18163  }
18164 
18165  /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
18166  if (layout->flags & NK_WINDOW_REMOVE_ROM) {
18167  layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
18168  layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
18169  }
18170  window->flags = layout->flags;
18171 
18172  /* property garbage collector */
18173  if (window->property.active && window->property.old != window->property.seq &&
18174  window->property.active == window->property.prev) {
18175  nk_zero(&window->property, sizeof(window->property));
18176  } else {
18177  window->property.old = window->property.seq;
18178  window->property.prev = window->property.active;
18179  window->property.seq = 0;
18180  }
18181  /* edit garbage collector */
18182  if (window->edit.active && window->edit.old != window->edit.seq &&
18183  window->edit.active == window->edit.prev) {
18184  nk_zero(&window->edit, sizeof(window->edit));
18185  } else {
18186  window->edit.old = window->edit.seq;
18187  window->edit.prev = window->edit.active;
18188  window->edit.seq = 0;
18189  }
18190  /* contextual garbage collector */
18191  if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
18192  window->popup.con_count = 0;
18193  window->popup.con_old = 0;
18194  window->popup.active_con = 0;
18195  } else {
18196  window->popup.con_old = window->popup.con_count;
18197  window->popup.con_count = 0;
18198  }
18199  window->popup.combo_count = 0;
18200  /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
18201  NK_ASSERT(!layout->row.tree_depth);
18202 }
18203 
18204 /* ----------------------------------------------------------------
18205  *
18206  * PAGE ELEMENT
18207  *
18208  * ---------------------------------------------------------------*/
18209 NK_INTERN struct nk_page_element*
18210 nk_create_page_element(struct nk_context *ctx)
18211 {
18212  struct nk_page_element *elem;
18213  if (ctx->freelist) {
18214  /* unlink page element from free list */
18215  elem = ctx->freelist;
18216  ctx->freelist = elem->next;
18217  } else if (ctx->use_pool) {
18218  /* allocate page element from memory pool */
18219  elem = nk_pool_alloc(&ctx->pool);
18220  NK_ASSERT(elem);
18221  if (!elem) return 0;
18222  } else {
18223  /* allocate new page element from back of fixed size memory buffer */
18224  NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
18225  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element);
18226  elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
18227  NK_ASSERT(elem);
18228  if (!elem) return 0;
18229  }
18230  nk_zero_struct(*elem);
18231  elem->next = 0;
18232  elem->prev = 0;
18233  return elem;
18234 }
18235 
18236 NK_INTERN void
18237 nk_link_page_element_into_freelist(struct nk_context *ctx,
18238  struct nk_page_element *elem)
18239 {
18240  /* link table into freelist */
18241  if (!ctx->freelist) {
18242  ctx->freelist = elem;
18243  } else {
18244  elem->next = ctx->freelist;
18245  ctx->freelist = elem;
18246  }
18247 }
18248 
18249 NK_INTERN void
18250 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
18251 {
18252  /* we have a pool so just add to free list */
18253  if (ctx->use_pool) {
18254  nk_link_page_element_into_freelist(ctx, elem);
18255  return;
18256  }
18257  /* if possible remove last element from back of fixed memory buffer */
18258  {void *elem_end = (void*)(elem + 1);
18259  void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
18260  if (elem_end == buffer_end)
18261  ctx->memory.size -= sizeof(struct nk_page_element);
18262  else nk_link_page_element_into_freelist(ctx, elem);}
18263 }
18264 
18265 /* ----------------------------------------------------------------
18266  *
18267  * PANEL
18268  *
18269  * ---------------------------------------------------------------*/
18270 NK_INTERN void*
18271 nk_create_panel(struct nk_context *ctx)
18272 {
18273  struct nk_page_element *elem;
18274  elem = nk_create_page_element(ctx);
18275  if (!elem) return 0;
18276  nk_zero_struct(*elem);
18277  return &elem->data.pan;
18278 }
18279 
18280 NK_INTERN void
18281 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
18282 {
18283  union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
18284  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18285  nk_free_page_element(ctx, pe);
18286 }
18287 
18288 /* ----------------------------------------------------------------
18289  *
18290  * TABLES
18291  *
18292  * ---------------------------------------------------------------*/
18293 NK_INTERN struct nk_table*
18294 nk_create_table(struct nk_context *ctx)
18295 {
18296  struct nk_page_element *elem;
18297  elem = nk_create_page_element(ctx);
18298  if (!elem) return 0;
18299  nk_zero_struct(*elem);
18300  return &elem->data.tbl;
18301 }
18302 
18303 NK_INTERN void
18304 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
18305 {
18306  union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
18307  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18308  nk_free_page_element(ctx, pe);
18309 }
18310 
18311 NK_INTERN void
18312 nk_push_table(struct nk_window *win, struct nk_table *tbl)
18313 {
18314  if (!win->tables) {
18315  win->tables = tbl;
18316  tbl->next = 0;
18317  tbl->prev = 0;
18318  tbl->size = 0;
18319  win->table_count = 1;
18320  return;
18321  }
18322  win->tables->prev = tbl;
18323  tbl->next = win->tables;
18324  tbl->prev = 0;
18325  tbl->size = 0;
18326  win->tables = tbl;
18327  win->table_count++;
18328 }
18329 
18330 NK_INTERN void
18331 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
18332 {
18333  if (win->tables == tbl)
18334  win->tables = tbl->next;
18335  if (tbl->next)
18336  tbl->next->prev = tbl->prev;
18337  if (tbl->prev)
18338  tbl->prev->next = tbl->next;
18339  tbl->next = 0;
18340  tbl->prev = 0;
18341 }
18342 
18343 NK_INTERN nk_uint*
18344 nk_add_value(struct nk_context *ctx, struct nk_window *win,
18345  nk_hash name, nk_uint value)
18346 {
18347  NK_ASSERT(ctx);
18348  NK_ASSERT(win);
18349  if (!win || !ctx) return 0;
18350  if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
18351  struct nk_table *tbl = nk_create_table(ctx);
18352  NK_ASSERT(tbl);
18353  if (!tbl) return 0;
18354  nk_push_table(win, tbl);
18355  }
18356  win->tables->seq = win->seq;
18357  win->tables->keys[win->tables->size] = name;
18358  win->tables->values[win->tables->size] = value;
18359  return &win->tables->values[win->tables->size++];
18360 }
18361 
18362 NK_INTERN nk_uint*
18363 nk_find_value(struct nk_window *win, nk_hash name)
18364 {
18365  struct nk_table *iter = win->tables;
18366  while (iter) {
18367  unsigned int i = 0;
18368  unsigned int size = iter->size;
18369  for (i = 0; i < size; ++i) {
18370  if (iter->keys[i] == name) {
18371  iter->seq = win->seq;
18372  return &iter->values[i];
18373  }
18374  } size = NK_VALUE_PAGE_CAPACITY;
18375  iter = iter->next;
18376  }
18377  return 0;
18378 }
18379 
18380 /* ----------------------------------------------------------------
18381  *
18382  * WINDOW
18383  *
18384  * ---------------------------------------------------------------*/
18385 NK_INTERN void*
18386 nk_create_window(struct nk_context *ctx)
18387 {
18388  struct nk_page_element *elem;
18389  elem = nk_create_page_element(ctx);
18390  if (!elem) return 0;
18391  elem->data.win.seq = ctx->seq;
18392  return &elem->data.win;
18393 }
18394 
18395 NK_INTERN void
18396 nk_free_window(struct nk_context *ctx, struct nk_window *win)
18397 {
18398  /* unlink windows from list */
18399  struct nk_table *it = win->tables;
18400  if (win->popup.win) {
18401  nk_free_window(ctx, win->popup.win);
18402  win->popup.win = 0;
18403  }
18404  win->next = 0;
18405  win->prev = 0;
18406 
18407  while (it) {
18408  /*free window state tables */
18409  struct nk_table *n = it->next;
18410  nk_remove_table(win, it);
18411  nk_free_table(ctx, it);
18412  if (it == win->tables)
18413  win->tables = n;
18414  it = n;
18415  }
18416 
18417  /* link windows into freelist */
18418  {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
18419  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18420  nk_free_page_element(ctx, pe);}
18421 }
18422 
18423 NK_INTERN struct nk_window*
18424 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
18425 {
18426  struct nk_window *iter;
18427  iter = ctx->begin;
18428  while (iter) {
18429  NK_ASSERT(iter != iter->next);
18430  if (iter->name == hash) {
18431  int max_len = nk_strlen(iter->name_string);
18432  if (!nk_stricmpn(iter->name_string, name, max_len))
18433  return iter;
18434  }
18435  iter = iter->next;
18436  }
18437  return 0;
18438 }
18439 
18440 enum nk_window_insert_location {
18441  NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
18442  NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
18443 };
18444 NK_INTERN void
18445 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
18446  enum nk_window_insert_location loc)
18447 {
18448  const struct nk_window *iter;
18449  NK_ASSERT(ctx);
18450  NK_ASSERT(win);
18451  if (!win || !ctx) return;
18452 
18453  iter = ctx->begin;
18454  while (iter) {
18455  NK_ASSERT(iter != iter->next);
18456  NK_ASSERT(iter != win);
18457  if (iter == win) return;
18458  iter = iter->next;
18459  }
18460 
18461  if (!ctx->begin) {
18462  win->next = 0;
18463  win->prev = 0;
18464  ctx->begin = win;
18465  ctx->end = win;
18466  ctx->count = 1;
18467  return;
18468  }
18469  if (loc == NK_INSERT_BACK) {
18470  struct nk_window *end;
18471  end = ctx->end;
18472  end->flags |= NK_WINDOW_ROM;
18473  end->next = win;
18474  win->prev = ctx->end;
18475  win->next = 0;
18476  ctx->end = win;
18477  ctx->active = ctx->end;
18478  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18479  } else {
18480  ctx->begin->prev = win;
18481  win->next = ctx->begin;
18482  win->prev = 0;
18483  ctx->begin = win;
18484  ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
18485  }
18486  ctx->count++;
18487 }
18488 
18489 NK_INTERN void
18490 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
18491 {
18492  if (win == ctx->begin || win == ctx->end) {
18493  if (win == ctx->begin) {
18494  ctx->begin = win->next;
18495  if (win->next)
18496  win->next->prev = 0;
18497  }
18498  if (win == ctx->end) {
18499  ctx->end = win->prev;
18500  if (win->prev)
18501  win->prev->next = 0;
18502  }
18503  } else {
18504  if (win->next)
18505  win->next->prev = win->prev;
18506  if (win->prev)
18507  win->prev->next = win->next;
18508  }
18509  if (win == ctx->active || !ctx->active) {
18510  ctx->active = ctx->end;
18511  if (ctx->end)
18512  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18513  }
18514  win->next = 0;
18515  win->prev = 0;
18516  ctx->count--;
18517 }
18518 
18519 NK_API int
18520 nk_begin(struct nk_context *ctx, const char *title,
18521  struct nk_rect bounds, nk_flags flags)
18522 {
18523  return nk_begin_titled(ctx, title, title, bounds, flags);
18524 }
18525 
18526 NK_API int
18527 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
18528  struct nk_rect bounds, nk_flags flags)
18529 {
18530  struct nk_window *win;
18531  struct nk_style *style;
18532  nk_hash title_hash;
18533  int title_len;
18534  int ret = 0;
18535 
18536  NK_ASSERT(ctx);
18537  NK_ASSERT(name);
18538  NK_ASSERT(title);
18539  NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
18540  NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
18541  if (!ctx || ctx->current || !title || !name)
18542  return 0;
18543 
18544  /* find or create window */
18545  style = &ctx->style;
18546  title_len = (int)nk_strlen(name);
18547  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18548  win = nk_find_window(ctx, title_hash, name);
18549  if (!win) {
18550  /* create new window */
18551  nk_size name_length = (nk_size)nk_strlen(name);
18552  win = (struct nk_window*)nk_create_window(ctx);
18553  NK_ASSERT(win);
18554  if (!win) return 0;
18555 
18556  if (flags & NK_WINDOW_BACKGROUND)
18557  nk_insert_window(ctx, win, NK_INSERT_FRONT);
18558  else nk_insert_window(ctx, win, NK_INSERT_BACK);
18559  nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
18560 
18561  win->flags = flags;
18562  win->bounds = bounds;
18563  win->name = title_hash;
18564  name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
18565  NK_MEMCPY(win->name_string, name, name_length);
18566  win->name_string[name_length] = 0;
18567  win->popup.win = 0;
18568  if (!ctx->active)
18569  ctx->active = win;
18570  } else {
18571  /* update window */
18572  win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
18573  win->flags |= flags;
18574  if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
18575  win->bounds = bounds;
18576  /* If this assert triggers you either:
18577  *
18578  * I.) Have more than one window with the same name or
18579  * II.) You forgot to actually draw the window.
18580  * More specific you did not call `nk_clear` (nk_clear will be
18581  * automatically called for you if you are using one of the
18582  * provided demo backends). */
18583  NK_ASSERT(win->seq != ctx->seq);
18584  win->seq = ctx->seq;
18585  if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN))
18586  ctx->active = win;
18587  }
18588  if (win->flags & NK_WINDOW_HIDDEN) {
18589  ctx->current = win;
18590  win->layout = 0;
18591  return 0;
18592  }
18593 
18594  /* window overlapping */
18595  if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
18596  {
18597  int inpanel, ishovered;
18598  struct nk_window *iter = win;
18599  float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
18600  (2.0f * style->window.header.label_padding.y);
18601  struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
18602  win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
18603 
18604  /* activate window if hovered and no other window is overlapping this window */
18605  nk_start(ctx, win);
18606  inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
18607  inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
18608  ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
18609  if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
18610  iter = win->next;
18611  while (iter) {
18612  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18613  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18614  if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18615  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18616  (!(iter->flags & NK_WINDOW_HIDDEN)))
18617  break;
18618 
18619  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18620  NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18621  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18622  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18623  break;
18624  iter = iter->next;
18625  }
18626  }
18627 
18628  /* activate window if clicked */
18629  if (iter && inpanel && (win != ctx->end)) {
18630  iter = win->next;
18631  while (iter) {
18632  /* try to find a panel with higher priority in the same position */
18633  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18634  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18635  if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
18636  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18637  !(iter->flags & NK_WINDOW_HIDDEN))
18638  break;
18639  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18640  NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18641  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18642  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18643  break;
18644  iter = iter->next;
18645  }
18646  }
18647  if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
18648  win->flags |= (nk_flags)NK_WINDOW_ROM;
18649  iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
18650  ctx->active = iter;
18651  if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
18652  /* current window is active in that position so transfer to top
18653  * at the highest priority in stack */
18654  nk_remove_window(ctx, iter);
18655  nk_insert_window(ctx, iter, NK_INSERT_BACK);
18656  }
18657  } else {
18658  if (!iter && ctx->end != win) {
18659  if (!(win->flags & NK_WINDOW_BACKGROUND)) {
18660  /* current window is active in that position so transfer to top
18661  * at the highest priority in stack */
18662  nk_remove_window(ctx, win);
18663  nk_insert_window(ctx, win, NK_INSERT_BACK);
18664  }
18665  win->flags &= ~(nk_flags)NK_WINDOW_ROM;
18666  ctx->active = win;
18667  }
18668  if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
18669  win->flags |= NK_WINDOW_ROM;
18670  }
18671  }
18672 
18673  win->layout = (struct nk_panel*)nk_create_panel(ctx);
18674  ctx->current = win;
18675  ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
18676  win->layout->offset_x = &win->scrollbar.x;
18677  win->layout->offset_y = &win->scrollbar.y;
18678  return ret;
18679 }
18680 
18681 NK_API void
18682 nk_end(struct nk_context *ctx)
18683 {
18684  struct nk_panel *layout;
18685  NK_ASSERT(ctx);
18686  NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
18687  if (!ctx || !ctx->current)
18688  return;
18689 
18690  layout = ctx->current->layout;
18691  if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
18692  ctx->current = 0;
18693  return;
18694  }
18695  nk_panel_end(ctx);
18696  nk_free_panel(ctx, ctx->current->layout);
18697  ctx->current = 0;
18698 }
18699 
18700 NK_API struct nk_rect
18702 {
18703  NK_ASSERT(ctx);
18704  NK_ASSERT(ctx->current);
18705  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18706  return ctx->current->bounds;
18707 }
18708 
18709 NK_API struct nk_vec2
18711 {
18712  NK_ASSERT(ctx);
18713  NK_ASSERT(ctx->current);
18714  if (!ctx || !ctx->current) return nk_vec2(0,0);
18715  return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
18716 }
18717 
18718 NK_API struct nk_vec2
18720 {
18721  NK_ASSERT(ctx);
18722  NK_ASSERT(ctx->current);
18723  if (!ctx || !ctx->current) return nk_vec2(0,0);
18724  return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
18725 }
18726 
18727 NK_API float
18728 nk_window_get_width(const struct nk_context *ctx)
18729 {
18730  NK_ASSERT(ctx);
18731  NK_ASSERT(ctx->current);
18732  if (!ctx || !ctx->current) return 0;
18733  return ctx->current->bounds.w;
18734 }
18735 
18736 NK_API float
18737 nk_window_get_height(const struct nk_context *ctx)
18738 {
18739  NK_ASSERT(ctx);
18740  NK_ASSERT(ctx->current);
18741  if (!ctx || !ctx->current) return 0;
18742  return ctx->current->bounds.h;
18743 }
18744 
18745 NK_API struct nk_rect
18747 {
18748  NK_ASSERT(ctx);
18749  NK_ASSERT(ctx->current);
18750  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18751  return ctx->current->layout->clip;
18752 }
18753 
18754 NK_API struct nk_vec2
18756 {
18757  NK_ASSERT(ctx);
18758  NK_ASSERT(ctx->current);
18759  NK_ASSERT(ctx->current->layout);
18760  if (!ctx || !ctx->current) return nk_vec2(0,0);
18761  return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
18762 }
18763 
18764 NK_API struct nk_vec2
18766 {
18767  NK_ASSERT(ctx);
18768  NK_ASSERT(ctx->current);
18769  NK_ASSERT(ctx->current->layout);
18770  if (!ctx || !ctx->current) return nk_vec2(0,0);
18771  return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
18772  ctx->current->layout->clip.y + ctx->current->layout->clip.h);
18773 }
18774 
18775 NK_API struct nk_vec2
18777 {
18778  NK_ASSERT(ctx);
18779  NK_ASSERT(ctx->current);
18780  NK_ASSERT(ctx->current->layout);
18781  if (!ctx || !ctx->current) return nk_vec2(0,0);
18782  return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
18783 }
18784 
18785 NK_API struct nk_command_buffer*
18786 nk_window_get_canvas(struct nk_context *ctx)
18787 {
18788  NK_ASSERT(ctx);
18789  NK_ASSERT(ctx->current);
18790  NK_ASSERT(ctx->current->layout);
18791  if (!ctx || !ctx->current) return 0;
18792  return &ctx->current->buffer;
18793 }
18794 
18795 NK_API struct nk_panel*
18796 nk_window_get_panel(struct nk_context *ctx)
18797 {
18798  NK_ASSERT(ctx);
18799  NK_ASSERT(ctx->current);
18800  if (!ctx || !ctx->current) return 0;
18801  return ctx->current->layout;
18802 }
18803 
18804 NK_API int
18805 nk_window_has_focus(const struct nk_context *ctx)
18806 {
18807  NK_ASSERT(ctx);
18808  NK_ASSERT(ctx->current);
18809  NK_ASSERT(ctx->current->layout);
18810  if (!ctx || !ctx->current) return 0;
18811  return ctx->current == ctx->active;
18812 }
18813 
18814 NK_API int
18815 nk_window_is_hovered(struct nk_context *ctx)
18816 {
18817  NK_ASSERT(ctx);
18818  NK_ASSERT(ctx->current);
18819  if (!ctx || !ctx->current) return 0;
18820  if(ctx->current->flags & NK_WINDOW_HIDDEN)
18821  return 0;
18822  return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
18823 }
18824 
18825 NK_API int
18827 {
18828  struct nk_window *iter;
18829  NK_ASSERT(ctx);
18830  if (!ctx) return 0;
18831  iter = ctx->begin;
18832  while (iter) {
18833  /* check if window is being hovered */
18834  if(!(iter->flags & NK_WINDOW_HIDDEN)) {
18835  /* check if window popup is being hovered */
18836  if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
18837  return 1;
18838 
18839  if (iter->flags & NK_WINDOW_MINIMIZED) {
18840  struct nk_rect header = iter->bounds;
18841  header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
18842  if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
18843  return 1;
18844  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
18845  return 1;
18846  }
18847  }
18848  iter = iter->next;
18849  }
18850  return 0;
18851 }
18852 
18853 NK_API int
18854 nk_item_is_any_active(struct nk_context *ctx)
18855 {
18856  int any_hovered = nk_window_is_any_hovered(ctx);
18857  int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18858  return any_hovered || any_active;
18859 }
18860 
18861 NK_API int
18862 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
18863 {
18864  int title_len;
18865  nk_hash title_hash;
18866  struct nk_window *win;
18867  NK_ASSERT(ctx);
18868  if (!ctx) return 0;
18869 
18870  title_len = (int)nk_strlen(name);
18871  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18872  win = nk_find_window(ctx, title_hash, name);
18873  if (!win) return 0;
18874  return win->flags & NK_WINDOW_MINIMIZED;
18875 }
18876 
18877 NK_API int
18878 nk_window_is_closed(struct nk_context *ctx, const char *name)
18879 {
18880  int title_len;
18881  nk_hash title_hash;
18882  struct nk_window *win;
18883  NK_ASSERT(ctx);
18884  if (!ctx) return 1;
18885 
18886  title_len = (int)nk_strlen(name);
18887  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18888  win = nk_find_window(ctx, title_hash, name);
18889  if (!win) return 1;
18890  return (win->flags & NK_WINDOW_CLOSED);
18891 }
18892 
18893 NK_API int
18894 nk_window_is_hidden(struct nk_context *ctx, const char *name)
18895 {
18896  int title_len;
18897  nk_hash title_hash;
18898  struct nk_window *win;
18899  NK_ASSERT(ctx);
18900  if (!ctx) return 1;
18901 
18902  title_len = (int)nk_strlen(name);
18903  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18904  win = nk_find_window(ctx, title_hash, name);
18905  if (!win) return 1;
18906  return (win->flags & NK_WINDOW_HIDDEN);
18907 }
18908 
18909 NK_API int
18910 nk_window_is_active(struct nk_context *ctx, const char *name)
18911 {
18912  int title_len;
18913  nk_hash title_hash;
18914  struct nk_window *win;
18915  NK_ASSERT(ctx);
18916  if (!ctx) return 0;
18917 
18918  title_len = (int)nk_strlen(name);
18919  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18920  win = nk_find_window(ctx, title_hash, name);
18921  if (!win) return 0;
18922  return win == ctx->active;
18923 }
18924 
18925 NK_API struct nk_window*
18926 nk_window_find(struct nk_context *ctx, const char *name)
18927 {
18928  int title_len;
18929  nk_hash title_hash;
18930  title_len = (int)nk_strlen(name);
18931  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18932  return nk_find_window(ctx, title_hash, name);
18933 }
18934 
18935 NK_API void
18936 nk_window_close(struct nk_context *ctx, const char *name)
18937 {
18938  struct nk_window *win;
18939  NK_ASSERT(ctx);
18940  if (!ctx) return;
18941  win = nk_window_find(ctx, name);
18942  if (!win) return;
18943  NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
18944  if (ctx->current == win) return;
18945  win->flags |= NK_WINDOW_HIDDEN;
18946  win->flags |= NK_WINDOW_CLOSED;
18947 }
18948 
18949 NK_API void
18950 nk_window_set_bounds(struct nk_context *ctx, struct nk_rect bounds)
18951 {
18952  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18953  if (!ctx || !ctx->current) return;
18954  ctx->current->bounds = bounds;
18955 }
18956 
18957 NK_API void
18958 nk_window_set_position(struct nk_context *ctx, struct nk_vec2 pos)
18959 {
18960  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18961  if (!ctx || !ctx->current) return;
18962  ctx->current->bounds.x = pos.x;
18963  ctx->current->bounds.y = pos.y;
18964 }
18965 
18966 NK_API void
18967 nk_window_set_size(struct nk_context *ctx, struct nk_vec2 size)
18968 {
18969  NK_ASSERT(ctx); NK_ASSERT(ctx->current);
18970  if (!ctx || !ctx->current) return;
18971  ctx->current->bounds.w = size.x;
18972  ctx->current->bounds.h = size.y;
18973 }
18974 
18975 NK_API void
18976 nk_window_collapse(struct nk_context *ctx, const char *name,
18977  enum nk_collapse_states c)
18978 {
18979  int title_len;
18980  nk_hash title_hash;
18981  struct nk_window *win;
18982  NK_ASSERT(ctx);
18983  if (!ctx) return;
18984 
18985  title_len = (int)nk_strlen(name);
18986  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18987  win = nk_find_window(ctx, title_hash, name);
18988  if (!win) return;
18989  if (c == NK_MINIMIZED)
18990  win->flags |= NK_WINDOW_MINIMIZED;
18991  else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
18992 }
18993 
18994 NK_API void
18995 nk_window_collapse_if(struct nk_context *ctx, const char *name,
18996  enum nk_collapse_states c, int cond)
18997 {
18998  NK_ASSERT(ctx);
18999  if (!ctx || !cond) return;
19000  nk_window_collapse(ctx, name, c);
19001 }
19002 
19003 NK_API void
19004 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
19005 {
19006  int title_len;
19007  nk_hash title_hash;
19008  struct nk_window *win;
19009  NK_ASSERT(ctx);
19010  if (!ctx) return;
19011 
19012  title_len = (int)nk_strlen(name);
19013  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19014  win = nk_find_window(ctx, title_hash, name);
19015  if (!win) return;
19016  if (s == NK_HIDDEN) {
19017  win->flags |= NK_WINDOW_HIDDEN;
19018  } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
19019 }
19020 
19021 NK_API void
19022 nk_window_show_if(struct nk_context *ctx, const char *name,
19023  enum nk_show_states s, int cond)
19024 {
19025  NK_ASSERT(ctx);
19026  if (!ctx || !cond) return;
19027  nk_window_show(ctx, name, s);
19028 }
19029 
19030 NK_API void
19031 nk_window_set_focus(struct nk_context *ctx, const char *name)
19032 {
19033  int title_len;
19034  nk_hash title_hash;
19035  struct nk_window *win;
19036  NK_ASSERT(ctx);
19037  if (!ctx) return;
19038 
19039  title_len = (int)nk_strlen(name);
19040  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19041  win = nk_find_window(ctx, title_hash, name);
19042  if (win && ctx->end != win) {
19043  nk_remove_window(ctx, win);
19044  nk_insert_window(ctx, win, NK_INSERT_BACK);
19045  }
19046  ctx->active = win;
19047 }
19048 
19049 /*----------------------------------------------------------------
19050  *
19051  * MENUBAR
19052  *
19053  * --------------------------------------------------------------*/
19054 NK_API void
19055 nk_menubar_begin(struct nk_context *ctx)
19056 {
19057  struct nk_panel *layout;
19058  NK_ASSERT(ctx);
19059  NK_ASSERT(ctx->current);
19060  NK_ASSERT(ctx->current->layout);
19061  if (!ctx || !ctx->current || !ctx->current->layout)
19062  return;
19063 
19064  layout = ctx->current->layout;
19065  NK_ASSERT(layout->at_y == layout->bounds.y);
19066  /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
19067  If you want a menubar the first nuklear function after `nk_begin` has to be a
19068  `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
19069  widgets (also supports multiple rows).
19070  Example:
19071  if (nk_begin(...)) {
19072  nk_menubar_begin(...);
19073  nk_layout_xxxx(...);
19074  nk_button(...);
19075  nk_layout_xxxx(...);
19076  nk_button(...);
19077  nk_menubar_end(...);
19078  }
19079  nk_end(...);
19080  */
19081  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
19082  return;
19083 
19084  layout->menu.x = layout->at_x;
19085  layout->menu.y = layout->at_y + layout->row.height;
19086  layout->menu.w = layout->bounds.w;
19087  layout->menu.offset.x = *layout->offset_x;
19088  layout->menu.offset.y = *layout->offset_y;
19089  *layout->offset_y = 0;
19090 }
19091 
19092 NK_API void
19093 nk_menubar_end(struct nk_context *ctx)
19094 {
19095  struct nk_window *win;
19096  struct nk_panel *layout;
19097  struct nk_command_buffer *out;
19098 
19099  NK_ASSERT(ctx);
19100  NK_ASSERT(ctx->current);
19101  NK_ASSERT(ctx->current->layout);
19102  if (!ctx || !ctx->current || !ctx->current->layout)
19103  return;
19104 
19105  win = ctx->current;
19106  out = &win->buffer;
19107  layout = win->layout;
19108  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
19109  return;
19110 
19111  layout->menu.h = layout->at_y - layout->menu.y;
19112  layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
19113  layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
19114 
19115  *layout->offset_x = layout->menu.offset.x;
19116  *layout->offset_y = layout->menu.offset.y;
19117  layout->at_y = layout->bounds.y - layout->row.height;
19118 
19119  layout->clip.y = layout->bounds.y;
19120  layout->clip.h = layout->bounds.h;
19121  nk_push_scissor(out, layout->clip);
19122 }
19123 /* -------------------------------------------------------------
19124  *
19125  * LAYOUT
19126  *
19127  * --------------------------------------------------------------*/
19128 NK_API void
19129 nk_layout_set_min_row_height(struct nk_context *ctx, float height)
19130 {
19131  struct nk_window *win;
19132  struct nk_panel *layout;
19133 
19134  NK_ASSERT(ctx);
19135  NK_ASSERT(ctx->current);
19136  NK_ASSERT(ctx->current->layout);
19137  if (!ctx || !ctx->current || !ctx->current->layout)
19138  return;
19139 
19140  win = ctx->current;
19141  layout = win->layout;
19142  layout->row.min_height = height;
19143 }
19144 
19145 NK_API void
19147 {
19148  struct nk_window *win;
19149  struct nk_panel *layout;
19150 
19151  NK_ASSERT(ctx);
19152  NK_ASSERT(ctx->current);
19153  NK_ASSERT(ctx->current->layout);
19154  if (!ctx || !ctx->current || !ctx->current->layout)
19155  return;
19156 
19157  win = ctx->current;
19158  layout = win->layout;
19159  layout->row.min_height = ctx->style.font->height;
19160  layout->row.min_height += ctx->style.text.padding.y*2;
19161  layout->row.min_height += ctx->style.window.min_row_height_padding*2;
19162 }
19163 
19164 NK_INTERN float
19165 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
19166  float total_space, int columns)
19167 {
19168  float panel_padding;
19169  float panel_spacing;
19170  float panel_space;
19171 
19172  struct nk_vec2 spacing;
19173  struct nk_vec2 padding;
19174 
19175  spacing = style->window.spacing;
19176  padding = nk_panel_get_padding(style, type);
19177 
19178  /* calculate the usable panel space */
19179  panel_padding = 2 * padding.x;
19180  panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
19181  panel_space = total_space - panel_padding - panel_spacing;
19182  return panel_space;
19183 }
19184 
19185 NK_INTERN void
19186 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
19187  float height, int cols)
19188 {
19189  struct nk_panel *layout;
19190  const struct nk_style *style;
19191  struct nk_command_buffer *out;
19192 
19193  struct nk_vec2 item_spacing;
19194  struct nk_color color;
19195 
19196  NK_ASSERT(ctx);
19197  NK_ASSERT(ctx->current);
19198  NK_ASSERT(ctx->current->layout);
19199  if (!ctx || !ctx->current || !ctx->current->layout)
19200  return;
19201 
19202  /* prefetch some configuration data */
19203  layout = win->layout;
19204  style = &ctx->style;
19205  out = &win->buffer;
19206  color = style->window.background;
19207  item_spacing = style->window.spacing;
19208 
19209  /* if one of these triggers you forgot to add an `if` condition around either
19210  a window, group, popup, combobox or contextual menu `begin` and `end` block.
19211  Example:
19212  if (nk_begin(...) {...} nk_end(...); or
19213  if (nk_group_begin(...) { nk_group_end(...);} */
19214  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
19215  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
19216  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
19217 
19218  /* update the current row and set the current row layout */
19219  layout->row.index = 0;
19220  layout->at_y += layout->row.height;
19221  layout->row.columns = cols;
19222  if (height == 0.0f)
19223  layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
19224  else layout->row.height = height + item_spacing.y;
19225 
19226  layout->row.item_offset = 0;
19227  if (layout->flags & NK_WINDOW_DYNAMIC) {
19228  /* draw background for dynamic panels */
19229  struct nk_rect background;
19230  background.x = win->bounds.x;
19231  background.w = win->bounds.w;
19232  background.y = layout->at_y - 1.0f;
19233  background.h = layout->row.height + 1.0f;
19234  nk_fill_rect(out, background, 0, color);
19235  }
19236 }
19237 
19238 NK_INTERN void
19239 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
19240  float height, int cols, int width)
19241 {
19242  /* update the current row and set the current row layout */
19243  struct nk_window *win;
19244  NK_ASSERT(ctx);
19245  NK_ASSERT(ctx->current);
19246  NK_ASSERT(ctx->current->layout);
19247  if (!ctx || !ctx->current || !ctx->current->layout)
19248  return;
19249 
19250  win = ctx->current;
19251  nk_panel_layout(ctx, win, height, cols);
19252  if (fmt == NK_DYNAMIC)
19254  else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
19255 
19256  win->layout->row.ratio = 0;
19257  win->layout->row.filled = 0;
19258  win->layout->row.item_offset = 0;
19259  win->layout->row.item_width = (float)width;
19260 }
19261 
19262 NK_API float
19263 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
19264 {
19265  struct nk_window *win;
19266  NK_ASSERT(ctx);
19267  NK_ASSERT(pixel_width);
19268  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
19269  win = ctx->current;
19270  return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
19271 }
19272 
19273 NK_API void
19274 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
19275 {
19276  nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
19277 }
19278 
19279 NK_API void
19280 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
19281 {
19282  nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
19283 }
19284 
19285 NK_API void
19286 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19287  float row_height, int cols)
19288 {
19289  struct nk_window *win;
19290  struct nk_panel *layout;
19291 
19292  NK_ASSERT(ctx);
19293  NK_ASSERT(ctx->current);
19294  NK_ASSERT(ctx->current->layout);
19295  if (!ctx || !ctx->current || !ctx->current->layout)
19296  return;
19297 
19298  win = ctx->current;
19299  layout = win->layout;
19300  nk_panel_layout(ctx, win, row_height, cols);
19301  if (fmt == NK_DYNAMIC)
19302  layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
19303  else layout->row.type = NK_LAYOUT_STATIC_ROW;
19304 
19305  layout->row.ratio = 0;
19306  layout->row.filled = 0;
19307  layout->row.item_width = 0;
19308  layout->row.item_offset = 0;
19309  layout->row.columns = cols;
19310 }
19311 
19312 NK_API void
19313 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
19314 {
19315  struct nk_window *win;
19316  struct nk_panel *layout;
19317 
19318  NK_ASSERT(ctx);
19319  NK_ASSERT(ctx->current);
19320  NK_ASSERT(ctx->current->layout);
19321  if (!ctx || !ctx->current || !ctx->current->layout)
19322  return;
19323 
19324  win = ctx->current;
19325  layout = win->layout;
19326  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19327  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19328  return;
19329 
19330  if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
19331  float ratio = ratio_or_width;
19332  if ((ratio + layout->row.filled) > 1.0f) return;
19333  if (ratio > 0.0f)
19334  layout->row.item_width = NK_SATURATE(ratio);
19335  else layout->row.item_width = 1.0f - layout->row.filled;
19336  } else layout->row.item_width = ratio_or_width;
19337 }
19338 
19339 NK_API void
19340 nk_layout_row_end(struct nk_context *ctx)
19341 {
19342  struct nk_window *win;
19343  struct nk_panel *layout;
19344 
19345  NK_ASSERT(ctx);
19346  NK_ASSERT(ctx->current);
19347  NK_ASSERT(ctx->current->layout);
19348  if (!ctx || !ctx->current || !ctx->current->layout)
19349  return;
19350 
19351  win = ctx->current;
19352  layout = win->layout;
19353  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19354  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19355  return;
19356  layout->row.item_width = 0;
19357  layout->row.item_offset = 0;
19358 }
19359 
19360 NK_API void
19361 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
19362  float height, int cols, const float *ratio)
19363 {
19364  int i;
19365  int n_undef = 0;
19366  struct nk_window *win;
19367  struct nk_panel *layout;
19368 
19369  NK_ASSERT(ctx);
19370  NK_ASSERT(ctx->current);
19371  NK_ASSERT(ctx->current->layout);
19372  if (!ctx || !ctx->current || !ctx->current->layout)
19373  return;
19374 
19375  win = ctx->current;
19376  layout = win->layout;
19377  nk_panel_layout(ctx, win, height, cols);
19378  if (fmt == NK_DYNAMIC) {
19379  /* calculate width of undefined widget ratios */
19380  float r = 0;
19381  layout->row.ratio = ratio;
19382  for (i = 0; i < cols; ++i) {
19383  if (ratio[i] < 0.0f)
19384  n_undef++;
19385  else r += ratio[i];
19386  }
19387  r = NK_SATURATE(1.0f - r);
19388  layout->row.type = NK_LAYOUT_DYNAMIC;
19389  layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
19390  } else {
19391  layout->row.ratio = ratio;
19392  layout->row.type = NK_LAYOUT_STATIC;
19393  layout->row.item_width = 0;
19394  layout->row.item_offset = 0;
19395  }
19396  layout->row.item_offset = 0;
19397  layout->row.filled = 0;
19398 }
19399 
19400 NK_API void
19401 nk_layout_row_template_begin(struct nk_context *ctx, float height)
19402 {
19403  struct nk_window *win;
19404  struct nk_panel *layout;
19405 
19406  NK_ASSERT(ctx);
19407  NK_ASSERT(ctx->current);
19408  NK_ASSERT(ctx->current->layout);
19409  if (!ctx || !ctx->current || !ctx->current->layout)
19410  return;
19411 
19412  win = ctx->current;
19413  layout = win->layout;
19414  nk_panel_layout(ctx, win, height, 1);
19415  layout->row.type = NK_LAYOUT_TEMPLATE;
19416  layout->row.columns = 0;
19417  layout->row.ratio = 0;
19418  layout->row.item_width = 0;
19419  layout->row.item_height = 0;
19420  layout->row.item_offset = 0;
19421  layout->row.filled = 0;
19422  layout->row.item.x = 0;
19423  layout->row.item.y = 0;
19424  layout->row.item.w = 0;
19425  layout->row.item.h = 0;
19426 }
19427 
19428 NK_API void
19430 {
19431  struct nk_window *win;
19432  struct nk_panel *layout;
19433 
19434  NK_ASSERT(ctx);
19435  NK_ASSERT(ctx->current);
19436  NK_ASSERT(ctx->current->layout);
19437  if (!ctx || !ctx->current || !ctx->current->layout)
19438  return;
19439 
19440  win = ctx->current;
19441  layout = win->layout;
19442  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19443  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19444  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19445  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19446  layout->row.templates[layout->row.columns++] = -1.0f;
19447 }
19448 
19449 NK_API void
19450 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
19451 {
19452  struct nk_window *win;
19453  struct nk_panel *layout;
19454 
19455  NK_ASSERT(ctx);
19456  NK_ASSERT(ctx->current);
19457  NK_ASSERT(ctx->current->layout);
19458  if (!ctx || !ctx->current || !ctx->current->layout)
19459  return;
19460 
19461  win = ctx->current;
19462  layout = win->layout;
19463  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19464  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19465  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19466  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19467  layout->row.templates[layout->row.columns++] = -min_width;
19468 }
19469 
19470 NK_API void
19471 nk_layout_row_template_push_static(struct nk_context *ctx, float width)
19472 {
19473  struct nk_window *win;
19474  struct nk_panel *layout;
19475 
19476  NK_ASSERT(ctx);
19477  NK_ASSERT(ctx->current);
19478  NK_ASSERT(ctx->current->layout);
19479  if (!ctx || !ctx->current || !ctx->current->layout)
19480  return;
19481 
19482  win = ctx->current;
19483  layout = win->layout;
19484  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19485  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19486  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19487  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19488  layout->row.templates[layout->row.columns++] = width;
19489 }
19490 
19491 NK_API void
19493 {
19494  struct nk_window *win;
19495  struct nk_panel *layout;
19496 
19497  int i = 0;
19498  int variable_count = 0;
19499  int min_variable_count = 0;
19500  float min_fixed_width = 0.0f;
19501  float total_fixed_width = 0.0f;
19502  float max_variable_width = 0.0f;
19503 
19504  NK_ASSERT(ctx);
19505  NK_ASSERT(ctx->current);
19506  NK_ASSERT(ctx->current->layout);
19507  if (!ctx || !ctx->current || !ctx->current->layout)
19508  return;
19509 
19510  win = ctx->current;
19511  layout = win->layout;
19512  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19513  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19514  for (i = 0; i < layout->row.columns; ++i) {
19515  float width = layout->row.templates[i];
19516  if (width >= 0.0f) {
19517  total_fixed_width += width;
19518  min_fixed_width += width;
19519  } else if (width < -1.0f) {
19520  width = -width;
19521  total_fixed_width += width;
19522  max_variable_width = NK_MAX(max_variable_width, width);
19523  variable_count++;
19524  } else {
19525  min_variable_count++;
19526  variable_count++;
19527  }
19528  }
19529  if (variable_count) {
19530  float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19531  layout->bounds.w, layout->row.columns);
19532  float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
19533  int enough_space = var_width >= max_variable_width;
19534  if (!enough_space)
19535  var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
19536  for (i = 0; i < layout->row.columns; ++i) {
19537  float *width = &layout->row.templates[i];
19538  *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
19539  }
19540  }
19541 }
19542 
19543 NK_API void
19544 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt,
19545  float height, int widget_count)
19546 {
19547  struct nk_window *win;
19548  struct nk_panel *layout;
19549 
19550  NK_ASSERT(ctx);
19551  NK_ASSERT(ctx->current);
19552  NK_ASSERT(ctx->current->layout);
19553  if (!ctx || !ctx->current || !ctx->current->layout)
19554  return;
19555 
19556  win = ctx->current;
19557  layout = win->layout;
19558  nk_panel_layout(ctx, win, height, widget_count);
19559  if (fmt == NK_STATIC)
19560  layout->row.type = NK_LAYOUT_STATIC_FREE;
19561  else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
19562 
19563  layout->row.ratio = 0;
19564  layout->row.filled = 0;
19565  layout->row.item_width = 0;
19566  layout->row.item_offset = 0;
19567 }
19568 
19569 NK_API void
19570 nk_layout_space_end(struct nk_context *ctx)
19571 {
19572  struct nk_window *win;
19573  struct nk_panel *layout;
19574 
19575  NK_ASSERT(ctx);
19576  NK_ASSERT(ctx->current);
19577  NK_ASSERT(ctx->current->layout);
19578  if (!ctx || !ctx->current || !ctx->current->layout)
19579  return;
19580 
19581  win = ctx->current;
19582  layout = win->layout;
19583  layout->row.item_width = 0;
19584  layout->row.item_height = 0;
19585  layout->row.item_offset = 0;
19586  nk_zero(&layout->row.item, sizeof(layout->row.item));
19587 }
19588 
19589 NK_API void
19590 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
19591 {
19592  struct nk_window *win;
19593  struct nk_panel *layout;
19594 
19595  NK_ASSERT(ctx);
19596  NK_ASSERT(ctx->current);
19597  NK_ASSERT(ctx->current->layout);
19598  if (!ctx || !ctx->current || !ctx->current->layout)
19599  return;
19600 
19601  win = ctx->current;
19602  layout = win->layout;
19603  layout->row.item = rect;
19604 }
19605 
19606 NK_API struct nk_rect
19608 {
19609  struct nk_rect ret;
19610  struct nk_window *win;
19611  struct nk_panel *layout;
19612 
19613  NK_ASSERT(ctx);
19614  NK_ASSERT(ctx->current);
19615  NK_ASSERT(ctx->current->layout);
19616  win = ctx->current;
19617  layout = win->layout;
19618 
19619  ret.x = layout->clip.x;
19620  ret.y = layout->clip.y;
19621  ret.w = layout->clip.w;
19622  ret.h = layout->row.height;
19623  return ret;
19624 }
19625 
19626 NK_API struct nk_rect
19628 {
19629  struct nk_rect ret;
19630  struct nk_window *win;
19631  struct nk_panel *layout;
19632 
19633  NK_ASSERT(ctx);
19634  NK_ASSERT(ctx->current);
19635  NK_ASSERT(ctx->current->layout);
19636  win = ctx->current;
19637  layout = win->layout;
19638 
19639  ret.x = layout->at_x;
19640  ret.y = layout->at_y;
19641  ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
19642  ret.h = layout->row.height;
19643  return ret;
19644 }
19645 
19646 NK_API struct nk_vec2
19647 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
19648 {
19649  struct nk_window *win;
19650  struct nk_panel *layout;
19651 
19652  NK_ASSERT(ctx);
19653  NK_ASSERT(ctx->current);
19654  NK_ASSERT(ctx->current->layout);
19655  win = ctx->current;
19656  layout = win->layout;
19657 
19658  ret.x += layout->at_x - (float)*layout->offset_x;
19659  ret.y += layout->at_y - (float)*layout->offset_y;
19660  return ret;
19661 }
19662 
19663 NK_API struct nk_vec2
19664 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
19665 {
19666  struct nk_window *win;
19667  struct nk_panel *layout;
19668 
19669  NK_ASSERT(ctx);
19670  NK_ASSERT(ctx->current);
19671  NK_ASSERT(ctx->current->layout);
19672  win = ctx->current;
19673  layout = win->layout;
19674 
19675  ret.x += -layout->at_x + (float)*layout->offset_x;
19676  ret.y += -layout->at_y + (float)*layout->offset_y;
19677  return ret;
19678 }
19679 
19680 NK_API struct nk_rect
19682 {
19683  struct nk_window *win;
19684  struct nk_panel *layout;
19685 
19686  NK_ASSERT(ctx);
19687  NK_ASSERT(ctx->current);
19688  NK_ASSERT(ctx->current->layout);
19689  win = ctx->current;
19690  layout = win->layout;
19691 
19692  ret.x += layout->at_x - (float)*layout->offset_x;
19693  ret.y += layout->at_y - (float)*layout->offset_y;
19694  return ret;
19695 }
19696 
19697 NK_API struct nk_rect
19699 {
19700  struct nk_window *win;
19701  struct nk_panel *layout;
19702 
19703  NK_ASSERT(ctx);
19704  NK_ASSERT(ctx->current);
19705  NK_ASSERT(ctx->current->layout);
19706  win = ctx->current;
19707  layout = win->layout;
19708 
19709  ret.x += -layout->at_x + (float)*layout->offset_x;
19710  ret.y += -layout->at_y + (float)*layout->offset_y;
19711  return ret;
19712 }
19713 
19714 NK_INTERN void
19715 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
19716 {
19717  struct nk_panel *layout = win->layout;
19718  struct nk_vec2 spacing = ctx->style.window.spacing;
19719  const float row_height = layout->row.height - spacing.y;
19720  nk_panel_layout(ctx, win, row_height, layout->row.columns);
19721 }
19722 
19723 NK_INTERN void
19724 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
19725  struct nk_window *win, int modify)
19726 {
19727  struct nk_panel *layout;
19728  const struct nk_style *style;
19729 
19730  struct nk_vec2 spacing;
19731  struct nk_vec2 padding;
19732 
19733  float item_offset = 0;
19734  float item_width = 0;
19735  float item_spacing = 0;
19736  float panel_space = 0;
19737 
19738  NK_ASSERT(ctx);
19739  NK_ASSERT(ctx->current);
19740  NK_ASSERT(ctx->current->layout);
19741  if (!ctx || !ctx->current || !ctx->current->layout)
19742  return;
19743 
19744  win = ctx->current;
19745  layout = win->layout;
19746  style = &ctx->style;
19747  NK_ASSERT(bounds);
19748 
19749  spacing = style->window.spacing;
19750  padding = nk_panel_get_padding(style, layout->type);
19751  panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19752  layout->bounds.w, layout->row.columns);
19753 
19754  /* calculate the width of one item inside the current layout space */
19755  switch (layout->row.type) {
19756  case NK_LAYOUT_DYNAMIC_FIXED: {
19757  /* scaling fixed size widgets item width */
19758  item_width = NK_MAX(1.0f,panel_space-1.0f) / (float)layout->row.columns;
19759  item_offset = (float)layout->row.index * item_width;
19760  item_spacing = (float)layout->row.index * spacing.x;
19761  } break;
19762  case NK_LAYOUT_DYNAMIC_ROW: {
19763  /* scaling single ratio widget width */
19764  item_width = layout->row.item_width * panel_space;
19765  item_offset = layout->row.item_offset;
19766  item_spacing = 0;
19767 
19768  if (modify) {
19769  layout->row.item_offset += item_width + spacing.x;
19770  layout->row.filled += layout->row.item_width;
19771  layout->row.index = 0;
19772  }
19773  } break;
19774  case NK_LAYOUT_DYNAMIC_FREE: {
19775  /* panel width depended free widget placing */
19776  bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
19777  bounds->x -= (float)*layout->offset_x;
19778  bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
19779  bounds->y -= (float)*layout->offset_y;
19780  bounds->w = layout->bounds.w * layout->row.item.w;
19781  bounds->h = layout->row.height * layout->row.item.h;
19782  return;
19783  } break;
19784  case NK_LAYOUT_DYNAMIC: {
19785  /* scaling arrays of panel width ratios for every widget */
19786  float ratio;
19787  NK_ASSERT(layout->row.ratio);
19788  ratio = (layout->row.ratio[layout->row.index] < 0) ?
19789  layout->row.item_width : layout->row.ratio[layout->row.index];
19790 
19791  item_spacing = (float)layout->row.index * spacing.x;
19792  item_width = (ratio * panel_space);
19793  item_offset = layout->row.item_offset;
19794 
19795  if (modify) {
19796  layout->row.item_offset += item_width;
19797  layout->row.filled += ratio;
19798  }
19799  } break;
19800  case NK_LAYOUT_STATIC_FIXED: {
19801  /* non-scaling fixed widgets item width */
19802  item_width = layout->row.item_width;
19803  item_offset = (float)layout->row.index * item_width;
19804  item_spacing = (float)layout->row.index * spacing.x;
19805  } break;
19806  case NK_LAYOUT_STATIC_ROW: {
19807  /* scaling single ratio widget width */
19808  item_width = layout->row.item_width;
19809  item_offset = layout->row.item_offset;
19810  item_spacing = (float)layout->row.index * spacing.x;
19811  if (modify) layout->row.item_offset += item_width;
19812  } break;
19813  case NK_LAYOUT_STATIC_FREE: {
19814  /* free widget placing */
19815  bounds->x = layout->at_x + layout->row.item.x;
19816  bounds->w = layout->row.item.w;
19817  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19818  layout->max_x = (bounds->x + bounds->w);
19819  bounds->x -= (float)*layout->offset_x;
19820  bounds->y = layout->at_y + layout->row.item.y;
19821  bounds->y -= (float)*layout->offset_y;
19822  bounds->h = layout->row.item.h;
19823  return;
19824  } break;
19825  case NK_LAYOUT_STATIC: {
19826  /* non-scaling array of panel pixel width for every widget */
19827  item_spacing = (float)layout->row.index * spacing.x;
19828  item_width = layout->row.ratio[layout->row.index];
19829  item_offset = layout->row.item_offset;
19830  if (modify) layout->row.item_offset += item_width;
19831  } break;
19832  case NK_LAYOUT_TEMPLATE: {
19833  /* stretchy row layout with combined dynamic/static widget width*/
19834  NK_ASSERT(layout->row.index < layout->row.columns);
19835  NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19836  item_width = layout->row.templates[layout->row.index];
19837  item_offset = layout->row.item_offset;
19838  item_spacing = (float)layout->row.index * spacing.x;
19839  if (modify) layout->row.item_offset += item_width;
19840  } break;
19841  default: NK_ASSERT(0); break;
19842  };
19843 
19844  /* set the bounds of the newly allocated widget */
19845  bounds->w = item_width;
19846  bounds->h = layout->row.height - spacing.y;
19847  bounds->y = layout->at_y - (float)*layout->offset_y;
19848  bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
19849  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19850  layout->max_x = bounds->x + bounds->w;
19851  bounds->x -= (float)*layout->offset_x;
19852 }
19853 
19854 NK_INTERN void
19855 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
19856 {
19857  struct nk_window *win;
19858  struct nk_panel *layout;
19859 
19860  NK_ASSERT(ctx);
19861  NK_ASSERT(ctx->current);
19862  NK_ASSERT(ctx->current->layout);
19863  if (!ctx || !ctx->current || !ctx->current->layout)
19864  return;
19865 
19866  /* check if the end of the row has been hit and begin new row if so */
19867  win = ctx->current;
19868  layout = win->layout;
19869  if (layout->row.index >= layout->row.columns)
19870  nk_panel_alloc_row(ctx, win);
19871 
19872  /* calculate widget position and size */
19873  nk_layout_widget_space(bounds, ctx, win, nk_true);
19874  layout->row.index++;
19875 }
19876 
19877 NK_INTERN void
19878 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
19879 {
19880  float y;
19881  int index;
19882  struct nk_window *win;
19883  struct nk_panel *layout;
19884 
19885  NK_ASSERT(ctx);
19886  NK_ASSERT(ctx->current);
19887  NK_ASSERT(ctx->current->layout);
19888  if (!ctx || !ctx->current || !ctx->current->layout)
19889  return;
19890 
19891  win = ctx->current;
19892  layout = win->layout;
19893  y = layout->at_y;
19894  index = layout->row.index;
19895  if (layout->row.index >= layout->row.columns) {
19896  layout->at_y += layout->row.height;
19897  layout->row.index = 0;
19898  }
19899  nk_layout_widget_space(bounds, ctx, win, nk_false);
19900  layout->at_y = y;
19901  layout->row.index = index;
19902 }
19903 
19904 NK_INTERN int
19905 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
19906  struct nk_image *img, const char *title, enum nk_collapse_states *state)
19907 {
19908  struct nk_window *win;
19909  struct nk_panel *layout;
19910  const struct nk_style *style;
19911  struct nk_command_buffer *out;
19912  const struct nk_input *in;
19913  const struct nk_style_button *button;
19914  enum nk_symbol_type symbol;
19915  float row_height;
19916 
19917  struct nk_vec2 item_spacing;
19918  struct nk_rect header = {0,0,0,0};
19919  struct nk_rect sym = {0,0,0,0};
19920  struct nk_text text;
19921 
19922  nk_flags ws = 0;
19923  enum nk_widget_layout_states widget_state;
19924 
19925  NK_ASSERT(ctx);
19926  NK_ASSERT(ctx->current);
19927  NK_ASSERT(ctx->current->layout);
19928  if (!ctx || !ctx->current || !ctx->current->layout)
19929  return 0;
19930 
19931  /* cache some data */
19932  win = ctx->current;
19933  layout = win->layout;
19934  out = &win->buffer;
19935  style = &ctx->style;
19936  item_spacing = style->window.spacing;
19937 
19938  /* calculate header bounds and draw background */
19939  row_height = style->font->height + 2 * style->tab.padding.y;
19940  nk_layout_set_min_row_height(ctx, row_height);
19941  nk_layout_row_dynamic(ctx, row_height, 1);
19943 
19944  widget_state = nk_widget(&header, ctx);
19945  if (type == NK_TREE_TAB) {
19946  const struct nk_style_item *background = &style->tab.background;
19947  if (background->type == NK_STYLE_ITEM_IMAGE) {
19948  nk_draw_image(out, header, &background->data.image, nk_white);
19949  text.background = nk_rgba(0,0,0,0);
19950  } else {
19951  text.background = background->data.color;
19952  nk_fill_rect(out, header, 0, style->tab.border_color);
19953  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
19954  style->tab.rounding, background->data.color);
19955  }
19956  } else text.background = style->window.background;
19957 
19958  /* update node state */
19959  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
19960  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
19961  if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
19962  *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;
19963 
19964  /* select correct button style */
19965  if (*state == NK_MAXIMIZED) {
19966  symbol = style->tab.sym_maximize;
19967  if (type == NK_TREE_TAB)
19968  button = &style->tab.tab_maximize_button;
19969  else button = &style->tab.node_maximize_button;
19970  } else {
19971  symbol = style->tab.sym_minimize;
19972  if (type == NK_TREE_TAB)
19973  button = &style->tab.tab_minimize_button;
19974  else button = &style->tab.node_minimize_button;
19975  }
19976 
19977  {/* draw triangle button */
19978  sym.w = sym.h = style->font->height;
19979  sym.y = header.y + style->tab.padding.y;
19980  sym.x = header.x + style->tab.padding.x;
19981  nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
19982  button, 0, style->font);
19983 
19984  if (img) {
19985  /* draw optional image icon */
19986  sym.x = sym.x + sym.w + 4 * item_spacing.x;
19987  nk_draw_image(&win->buffer, sym, img, nk_white);
19988  sym.w = style->font->height + style->tab.spacing.x;}
19989  }
19990 
19991  {/* draw label */
19992  struct nk_rect label;
19993  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
19994  label.x = sym.x + sym.w + item_spacing.x;
19995  label.y = sym.y;
19996  label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
19997  label.h = style->font->height;
19998  text.text = style->tab.text;
19999  text.padding = nk_vec2(0,0);
20000  nk_widget_text(out, label, title, nk_strlen(title), &text,
20001  NK_TEXT_LEFT, style->font);}
20002 
20003  /* increase x-axis cursor widget position pointer */
20004  if (*state == NK_MAXIMIZED) {
20005  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
20006  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
20007  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
20008  layout->row.tree_depth++;
20009  return nk_true;
20010  } else return nk_false;
20011 }
20012 
20013 NK_INTERN int
20014 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
20015  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
20016  const char *hash, int len, int line)
20017 {
20018  struct nk_window *win = ctx->current;
20019  int title_len = 0;
20020  nk_hash tree_hash = 0;
20021  nk_uint *state = 0;
20022 
20023  /* retrieve tree state from internal widget state tables */
20024  if (!hash) {
20025  title_len = (int)nk_strlen(title);
20026  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
20027  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
20028  state = nk_find_value(win, tree_hash);
20029  if (!state) {
20030  state = nk_add_value(ctx, win, tree_hash, 0);
20031  *state = initial_state;
20032  }
20033  return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
20034 }
20035 
20036 NK_API int
20037 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type,
20038  const char *title, enum nk_collapse_states *state)
20039 {return nk_tree_state_base(ctx, type, 0, title, state);}
20040 
20041 NK_API int
20042 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type,
20043  struct nk_image img, const char *title, enum nk_collapse_states *state)
20044 {return nk_tree_state_base(ctx, type, &img, title, state);}
20045 
20046 NK_API void
20047 nk_tree_state_pop(struct nk_context *ctx)
20048 {
20049  struct nk_window *win = 0;
20050  struct nk_panel *layout = 0;
20051 
20052  NK_ASSERT(ctx);
20053  NK_ASSERT(ctx->current);
20054  NK_ASSERT(ctx->current->layout);
20055  if (!ctx || !ctx->current || !ctx->current->layout)
20056  return;
20057 
20058  win = ctx->current;
20059  layout = win->layout;
20060  layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
20061  layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
20062  NK_ASSERT(layout->row.tree_depth);
20063  layout->row.tree_depth--;
20064 }
20065 
20066 NK_API int
20067 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
20068  const char *title, enum nk_collapse_states initial_state,
20069  const char *hash, int len, int line)
20070 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);}
20071 
20072 NK_API int
20073 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type,
20074  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
20075  const char *hash, int len,int seed)
20076 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);}
20077 
20078 NK_API void
20079 nk_tree_pop(struct nk_context *ctx)
20080 {nk_tree_state_pop(ctx);}
20081 
20082 /*----------------------------------------------------------------
20083  *
20084  * WIDGETS
20085  *
20086  * --------------------------------------------------------------*/
20087 NK_API struct nk_rect
20089 {
20090  struct nk_rect bounds;
20091  NK_ASSERT(ctx);
20092  NK_ASSERT(ctx->current);
20093  if (!ctx || !ctx->current)
20094  return nk_rect(0,0,0,0);
20095  nk_layout_peek(&bounds, ctx);
20096  return bounds;
20097 }
20098 
20099 NK_API struct nk_vec2
20101 {
20102  struct nk_rect bounds;
20103  NK_ASSERT(ctx);
20104  NK_ASSERT(ctx->current);
20105  if (!ctx || !ctx->current)
20106  return nk_vec2(0,0);
20107 
20108  nk_layout_peek(&bounds, ctx);
20109  return nk_vec2(bounds.x, bounds.y);
20110 }
20111 
20112 NK_API struct nk_vec2
20113 nk_widget_size(struct nk_context *ctx)
20114 {
20115  struct nk_rect bounds;
20116  NK_ASSERT(ctx);
20117  NK_ASSERT(ctx->current);
20118  if (!ctx || !ctx->current)
20119  return nk_vec2(0,0);
20120 
20121  nk_layout_peek(&bounds, ctx);
20122  return nk_vec2(bounds.w, bounds.h);
20123 }
20124 
20125 NK_API float
20126 nk_widget_width(struct nk_context *ctx)
20127 {
20128  struct nk_rect bounds;
20129  NK_ASSERT(ctx);
20130  NK_ASSERT(ctx->current);
20131  if (!ctx || !ctx->current)
20132  return 0;
20133 
20134  nk_layout_peek(&bounds, ctx);
20135  return bounds.w;
20136 }
20137 
20138 NK_API float
20139 nk_widget_height(struct nk_context *ctx)
20140 {
20141  struct nk_rect bounds;
20142  NK_ASSERT(ctx);
20143  NK_ASSERT(ctx->current);
20144  if (!ctx || !ctx->current)
20145  return 0;
20146 
20147  nk_layout_peek(&bounds, ctx);
20148  return bounds.h;
20149 }
20150 
20151 NK_API int
20152 nk_widget_is_hovered(struct nk_context *ctx)
20153 {
20154  struct nk_rect c, v;
20155  struct nk_rect bounds;
20156  NK_ASSERT(ctx);
20157  NK_ASSERT(ctx->current);
20158  if (!ctx || !ctx->current || ctx->active != ctx->current)
20159  return 0;
20160 
20161  c = ctx->current->layout->clip;
20162  c.x = (float)((int)c.x);
20163  c.y = (float)((int)c.y);
20164  c.w = (float)((int)c.w);
20165  c.h = (float)((int)c.h);
20166 
20167  nk_layout_peek(&bounds, ctx);
20168  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20169  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20170  return 0;
20171  return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
20172 }
20173 
20174 NK_API int
20175 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn)
20176 {
20177  struct nk_rect c, v;
20178  struct nk_rect bounds;
20179  NK_ASSERT(ctx);
20180  NK_ASSERT(ctx->current);
20181  if (!ctx || !ctx->current || ctx->active != ctx->current)
20182  return 0;
20183 
20184  c = ctx->current->layout->clip;
20185  c.x = (float)((int)c.x);
20186  c.y = (float)((int)c.y);
20187  c.w = (float)((int)c.w);
20188  c.h = (float)((int)c.h);
20189 
20190  nk_layout_peek(&bounds, ctx);
20191  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20192  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20193  return 0;
20194  return nk_input_mouse_clicked(&ctx->input, btn, bounds);
20195 }
20196 
20197 NK_API int
20198 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down)
20199 {
20200  struct nk_rect c, v;
20201  struct nk_rect bounds;
20202  NK_ASSERT(ctx);
20203  NK_ASSERT(ctx->current);
20204  if (!ctx || !ctx->current || ctx->active != ctx->current)
20205  return 0;
20206 
20207  c = ctx->current->layout->clip;
20208  c.x = (float)((int)c.x);
20209  c.y = (float)((int)c.y);
20210  c.w = (float)((int)c.w);
20211  c.h = (float)((int)c.h);
20212 
20213  nk_layout_peek(&bounds, ctx);
20214  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20215  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20216  return 0;
20217  return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
20218 }
20219 
20221 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
20222 {
20223  struct nk_rect c, v;
20224  struct nk_window *win;
20225  struct nk_panel *layout;
20226  const struct nk_input *in;
20227 
20228  NK_ASSERT(ctx);
20229  NK_ASSERT(ctx->current);
20230  NK_ASSERT(ctx->current->layout);
20231  if (!ctx || !ctx->current || !ctx->current->layout)
20232  return NK_WIDGET_INVALID;
20233 
20234  /* allocate space and check if the widget needs to be updated and drawn */
20235  nk_panel_alloc_space(bounds, ctx);
20236  win = ctx->current;
20237  layout = win->layout;
20238  in = &ctx->input;
20239  c = layout->clip;
20240 
20241  /* if one of these triggers you forgot to add an `if` condition around either
20242  a window, group, popup, combobox or contextual menu `begin` and `end` block.
20243  Example:
20244  if (nk_begin(...) {...} nk_end(...); or
20245  if (nk_group_begin(...) { nk_group_end(...);} */
20246  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
20247  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
20248  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
20249 
20250  /* need to convert to int here to remove floating point errors */
20251  bounds->x = (float)((int)bounds->x);
20252  bounds->y = (float)((int)bounds->y);
20253  bounds->w = (float)((int)bounds->w);
20254  bounds->h = (float)((int)bounds->h);
20255 
20256  c.x = (float)((int)c.x);
20257  c.y = (float)((int)c.y);
20258  c.w = (float)((int)c.w);
20259  c.h = (float)((int)c.h);
20260 
20261  nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
20262  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
20263  return NK_WIDGET_INVALID;
20264  if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
20265  return NK_WIDGET_ROM;
20266  return NK_WIDGET_VALID;
20267 }
20268 
20270 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
20271  struct nk_vec2 item_padding)
20272 {
20273  /* update the bounds to stand without padding */
20274  struct nk_window *win;
20275  struct nk_style *style;
20276  struct nk_panel *layout;
20277  enum nk_widget_layout_states state;
20278  struct nk_vec2 panel_padding;
20279 
20280  NK_ASSERT(ctx);
20281  NK_ASSERT(ctx->current);
20282  NK_ASSERT(ctx->current->layout);
20283  if (!ctx || !ctx->current || !ctx->current->layout)
20284  return NK_WIDGET_INVALID;
20285 
20286  win = ctx->current;
20287  style = &ctx->style;
20288  layout = win->layout;
20289  state = nk_widget(bounds, ctx);
20290 
20291  panel_padding = nk_panel_get_padding(style, layout->type);
20292  if (layout->row.index == 1) {
20293  bounds->w += panel_padding.x;
20294  bounds->x -= panel_padding.x;
20295  } else bounds->x -= item_padding.x;
20296 
20297  if (layout->row.index == layout->row.columns)
20298  bounds->w += panel_padding.x;
20299  else bounds->w += item_padding.x;
20300  return state;
20301 }
20302 
20303 /*----------------------------------------------------------------
20304  *
20305  * MISC
20306  *
20307  * --------------------------------------------------------------*/
20308 NK_API void
20309 nk_spacing(struct nk_context *ctx, int cols)
20310 {
20311  struct nk_window *win;
20312  struct nk_panel *layout;
20313  struct nk_rect none;
20314  int i, index, rows;
20315 
20316  NK_ASSERT(ctx);
20317  NK_ASSERT(ctx->current);
20318  NK_ASSERT(ctx->current->layout);
20319  if (!ctx || !ctx->current || !ctx->current->layout)
20320  return;
20321 
20322  /* spacing over row boundaries */
20323  win = ctx->current;
20324  layout = win->layout;
20325  index = (layout->row.index + cols) % layout->row.columns;
20326  rows = (layout->row.index + cols) / layout->row.columns;
20327  if (rows) {
20328  for (i = 0; i < rows; ++i)
20329  nk_panel_alloc_row(ctx, win);
20330  cols = index;
20331  }
20332  /* non table layout need to allocate space */
20333  if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
20334  layout->row.type != NK_LAYOUT_STATIC_FIXED) {
20335  for (i = 0; i < cols; ++i)
20336  nk_panel_alloc_space(&none, ctx);
20337  }
20338  layout->row.index = index;
20339 }
20340 
20341 /*----------------------------------------------------------------
20342  *
20343  * TEXT
20344  *
20345  * --------------------------------------------------------------*/
20346 NK_API void
20347 nk_text_colored(struct nk_context *ctx, const char *str, int len,
20348  nk_flags alignment, struct nk_color color)
20349 {
20350  struct nk_window *win;
20351  const struct nk_style *style;
20352 
20353  struct nk_vec2 item_padding;
20354  struct nk_rect bounds;
20355  struct nk_text text;
20356 
20357  NK_ASSERT(ctx);
20358  NK_ASSERT(ctx->current);
20359  NK_ASSERT(ctx->current->layout);
20360  if (!ctx || !ctx->current || !ctx->current->layout) return;
20361 
20362  win = ctx->current;
20363  style = &ctx->style;
20364  nk_panel_alloc_space(&bounds, ctx);
20365  item_padding = style->text.padding;
20366 
20367  text.padding.x = item_padding.x;
20368  text.padding.y = item_padding.y;
20369  text.background = style->window.background;
20370  text.text = color;
20371  nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
20372 }
20373 
20374 NK_API void
20375 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
20376  int len, struct nk_color color)
20377 {
20378  struct nk_window *win;
20379  const struct nk_style *style;
20380 
20381  struct nk_vec2 item_padding;
20382  struct nk_rect bounds;
20383  struct nk_text text;
20384 
20385  NK_ASSERT(ctx);
20386  NK_ASSERT(ctx->current);
20387  NK_ASSERT(ctx->current->layout);
20388  if (!ctx || !ctx->current || !ctx->current->layout) return;
20389 
20390  win = ctx->current;
20391  style = &ctx->style;
20392  nk_panel_alloc_space(&bounds, ctx);
20393  item_padding = style->text.padding;
20394 
20395  text.padding.x = item_padding.x;
20396  text.padding.y = item_padding.y;
20397  text.background = style->window.background;
20398  text.text = color;
20399  nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
20400 }
20401 
20402 #ifdef NK_INCLUDE_STANDARD_VARARGS
20403 NK_API void
20404 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
20405  struct nk_color color, const char *fmt, ...)
20406 {
20407  char buf[256];
20408  va_list args;
20409  va_start(args, fmt);
20410  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20411  nk_label_colored(ctx, buf, flags, color);
20412  va_end(args);
20413 }
20414 
20415 NK_API void
20416 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
20417  const char *fmt, ...)
20418 {
20419  char buf[256];
20420  va_list args;
20421  va_start(args, fmt);
20422  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20423  nk_label_colored_wrap(ctx, buf, color);
20424  va_end(args);
20425 }
20426 
20427 NK_API void
20428 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
20429 {
20430  char buf[256];
20431  va_list args;
20432  va_start(args, fmt);
20433  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20434  nk_label(ctx, buf, flags);
20435  va_end(args);
20436 }
20437 
20438 NK_API void
20439 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
20440 {
20441  char buf[256];
20442  va_list args;
20443  va_start(args, fmt);
20444  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20445  nk_label_wrap(ctx, buf);
20446  va_end(args);
20447 }
20448 
20449 NK_API void
20450 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
20451 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));}
20452 
20453 NK_API void
20454 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
20455 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);}
20456 
20457 NK_API void
20458 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
20459 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);}
20460 
20461 NK_API void
20462 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
20463 {
20464  double double_value = (double)value;
20465  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
20466 }
20467 
20468 NK_API void
20469 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
20470 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);}
20471 
20472 NK_API void
20473 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
20474 {
20475  double c[4]; nk_color_dv(c, color);
20476  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
20477  p, c[0], c[1], c[2], c[3]);
20478 }
20479 
20480 NK_API void
20481 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
20482 {
20483  char hex[16];
20484  nk_color_hex_rgba(hex, color);
20485  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
20486 }
20487 #endif
20488 
20489 NK_API void
20490 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
20491 {
20492  NK_ASSERT(ctx);
20493  if (!ctx) return;
20494  nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
20495 }
20496 
20497 NK_API void
20498 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
20499 {
20500  NK_ASSERT(ctx);
20501  if (!ctx) return;
20502  nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
20503 }
20504 
20505 NK_API void
20506 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
20507 {nk_text(ctx, str, nk_strlen(str), alignment);}
20508 
20509 NK_API void
20510 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
20511  struct nk_color color)
20512 {nk_text_colored(ctx, str, nk_strlen(str), align, color);}
20513 
20514 NK_API void
20515 nk_label_wrap(struct nk_context *ctx, const char *str)
20516 {nk_text_wrap(ctx, str, nk_strlen(str));}
20517 
20518 NK_API void
20519 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
20520 {nk_text_wrap_colored(ctx, str, nk_strlen(str), color);}
20521 
20522 NK_API void
20523 nk_image(struct nk_context *ctx, struct nk_image img)
20524 {
20525  struct nk_window *win;
20526  struct nk_rect bounds;
20527 
20528  NK_ASSERT(ctx);
20529  NK_ASSERT(ctx->current);
20530  NK_ASSERT(ctx->current->layout);
20531  if (!ctx || !ctx->current || !ctx->current->layout) return;
20532 
20533  win = ctx->current;
20534  if (!nk_widget(&bounds, ctx)) return;
20535  nk_draw_image(&win->buffer, bounds, &img, nk_white);
20536 }
20537 
20538 /*----------------------------------------------------------------
20539  *
20540  * BUTTON
20541  *
20542  * --------------------------------------------------------------*/
20543 NK_API void
20544 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20545 {
20546  NK_ASSERT(ctx);
20547  if (!ctx) return;
20548  ctx->button_behavior = behavior;
20549 }
20550 
20551 NK_API int
20552 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior)
20553 {
20554  struct nk_config_stack_button_behavior *button_stack;
20555  struct nk_config_stack_button_behavior_element *element;
20556 
20557  NK_ASSERT(ctx);
20558  if (!ctx) return 0;
20559 
20560  button_stack = &ctx->stacks.button_behaviors;
20561  NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
20562  if (button_stack->head >= (int)NK_LEN(button_stack->elements))
20563  return 0;
20564 
20565  element = &button_stack->elements[button_stack->head++];
20566  element->address = &ctx->button_behavior;
20567  element->old_value = ctx->button_behavior;
20568  ctx->button_behavior = behavior;
20569  return 1;
20570 }
20571 
20572 NK_API int
20574 {
20575  struct nk_config_stack_button_behavior *button_stack;
20576  struct nk_config_stack_button_behavior_element *element;
20577 
20578  NK_ASSERT(ctx);
20579  if (!ctx) return 0;
20580 
20581  button_stack = &ctx->stacks.button_behaviors;
20582  NK_ASSERT(button_stack->head > 0);
20583  if (button_stack->head < 1)
20584  return 0;
20585 
20586  element = &button_stack->elements[--button_stack->head];
20587  *element->address = element->old_value;
20588  return 1;
20589 }
20590 
20591 NK_API int
20592 nk_button_text_styled(struct nk_context *ctx,
20593  const struct nk_style_button *style, const char *title, int len)
20594 {
20595  struct nk_window *win;
20596  struct nk_panel *layout;
20597  const struct nk_input *in;
20598 
20599  struct nk_rect bounds;
20600  enum nk_widget_layout_states state;
20601 
20602  NK_ASSERT(ctx);
20603  NK_ASSERT(style);
20604  NK_ASSERT(ctx->current);
20605  NK_ASSERT(ctx->current->layout);
20606  if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
20607 
20608  win = ctx->current;
20609  layout = win->layout;
20610  state = nk_widget(&bounds, ctx);
20611 
20612  if (!state) return 0;
20613  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20614  return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
20615  title, len, style->text_alignment, ctx->button_behavior,
20616  style, in, ctx->style.font);
20617 }
20618 
20619 NK_API int
20620 nk_button_text(struct nk_context *ctx, const char *title, int len)
20621 {
20622  NK_ASSERT(ctx);
20623  if (!ctx) return 0;
20624  return nk_button_text_styled(ctx, &ctx->style.button, title, len);
20625 }
20626 
20627 NK_API int nk_button_label_styled(struct nk_context *ctx,
20628  const struct nk_style_button *style, const char *title)
20629 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));}
20630 
20631 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
20632 {return nk_button_text(ctx, title, nk_strlen(title));}
20633 
20634 NK_API int
20635 nk_button_color(struct nk_context *ctx, struct nk_color color)
20636 {
20637  struct nk_window *win;
20638  struct nk_panel *layout;
20639  const struct nk_input *in;
20640  struct nk_style_button button;
20641 
20642  int ret = 0;
20643  struct nk_rect bounds;
20644  struct nk_rect content;
20645  enum nk_widget_layout_states state;
20646 
20647  NK_ASSERT(ctx);
20648  NK_ASSERT(ctx->current);
20649  NK_ASSERT(ctx->current->layout);
20650  if (!ctx || !ctx->current || !ctx->current->layout)
20651  return 0;
20652 
20653  win = ctx->current;
20654  layout = win->layout;
20655 
20656  state = nk_widget(&bounds, ctx);
20657  if (!state) return 0;
20658  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20659 
20660  button = ctx->style.button;
20661  button.normal = nk_style_item_color(color);
20662  button.hover = nk_style_item_color(color);
20663  button.active = nk_style_item_color(color);
20664  ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
20665  &button, in, ctx->button_behavior, &content);
20666  nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
20667  return ret;
20668 }
20669 
20670 NK_API int
20672  const struct nk_style_button *style, enum nk_symbol_type symbol)
20673 {
20674  struct nk_window *win;
20675  struct nk_panel *layout;
20676  const struct nk_input *in;
20677 
20678  struct nk_rect bounds;
20679  enum nk_widget_layout_states state;
20680 
20681  NK_ASSERT(ctx);
20682  NK_ASSERT(ctx->current);
20683  NK_ASSERT(ctx->current->layout);
20684  if (!ctx || !ctx->current || !ctx->current->layout)
20685  return 0;
20686 
20687  win = ctx->current;
20688  layout = win->layout;
20689  state = nk_widget(&bounds, ctx);
20690  if (!state) return 0;
20691  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20692  return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20693  symbol, ctx->button_behavior, style, in, ctx->style.font);
20694 }
20695 
20696 NK_API int
20697 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
20698 {
20699  NK_ASSERT(ctx);
20700  if (!ctx) return 0;
20701  return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
20702 }
20703 
20704 NK_API int
20705 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
20706  struct nk_image img)
20707 {
20708  struct nk_window *win;
20709  struct nk_panel *layout;
20710  const struct nk_input *in;
20711 
20712  struct nk_rect bounds;
20713  enum nk_widget_layout_states state;
20714 
20715  NK_ASSERT(ctx);
20716  NK_ASSERT(ctx->current);
20717  NK_ASSERT(ctx->current->layout);
20718  if (!ctx || !ctx->current || !ctx->current->layout)
20719  return 0;
20720 
20721  win = ctx->current;
20722  layout = win->layout;
20723 
20724  state = nk_widget(&bounds, ctx);
20725  if (!state) return 0;
20726  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20727  return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20728  img, ctx->button_behavior, style, in);
20729 }
20730 
20731 NK_API int
20732 nk_button_image(struct nk_context *ctx, struct nk_image img)
20733 {
20734  NK_ASSERT(ctx);
20735  if (!ctx) return 0;
20736  return nk_button_image_styled(ctx, &ctx->style.button, img);
20737 }
20738 
20739 NK_API int
20741  const struct nk_style_button *style, enum nk_symbol_type symbol,
20742  const char *text, int len, nk_flags align)
20743 {
20744  struct nk_window *win;
20745  struct nk_panel *layout;
20746  const struct nk_input *in;
20747 
20748  struct nk_rect bounds;
20749  enum nk_widget_layout_states state;
20750 
20751  NK_ASSERT(ctx);
20752  NK_ASSERT(ctx->current);
20753  NK_ASSERT(ctx->current->layout);
20754  if (!ctx || !ctx->current || !ctx->current->layout)
20755  return 0;
20756 
20757  win = ctx->current;
20758  layout = win->layout;
20759 
20760  state = nk_widget(&bounds, ctx);
20761  if (!state) return 0;
20762  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20763  return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20764  symbol, text, len, align, ctx->button_behavior,
20765  style, ctx->style.font, in);
20766 }
20767 
20768 NK_API int
20769 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20770  const char* text, int len, nk_flags align)
20771 {
20772  NK_ASSERT(ctx);
20773  if (!ctx) return 0;
20774  return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20775 }
20776 
20777 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20778  const char *label, nk_flags align)
20779 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);}
20780 
20782  const struct nk_style_button *style, enum nk_symbol_type symbol,
20783  const char *title, nk_flags align)
20784 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);}
20785 
20786 NK_API int
20788  const struct nk_style_button *style, struct nk_image img, const char *text,
20789  int len, nk_flags align)
20790 {
20791  struct nk_window *win;
20792  struct nk_panel *layout;
20793  const struct nk_input *in;
20794 
20795  struct nk_rect bounds;
20796  enum nk_widget_layout_states state;
20797 
20798  NK_ASSERT(ctx);
20799  NK_ASSERT(ctx->current);
20800  NK_ASSERT(ctx->current->layout);
20801  if (!ctx || !ctx->current || !ctx->current->layout)
20802  return 0;
20803 
20804  win = ctx->current;
20805  layout = win->layout;
20806 
20807  state = nk_widget(&bounds, ctx);
20808  if (!state) return 0;
20809  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20810  return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20811  bounds, img, text, len, align, ctx->button_behavior,
20812  style, ctx->style.font, in);
20813 }
20814 
20815 NK_API int
20816 nk_button_image_text(struct nk_context *ctx, struct nk_image img,
20817  const char *text, int len, nk_flags align)
20818 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);}
20819 
20820 
20821 NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img,
20822  const char *label, nk_flags align)
20823 {return nk_button_image_text(ctx, img, label, nk_strlen(label), align);}
20824 
20826  const struct nk_style_button *style, struct nk_image img,
20827  const char *label, nk_flags text_alignment)
20828 {return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);}
20829 
20830 /*----------------------------------------------------------------
20831  *
20832  * SELECTABLE
20833  *
20834  * --------------------------------------------------------------*/
20835 NK_API int
20836 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20837  nk_flags align, int *value)
20838 {
20839  struct nk_window *win;
20840  struct nk_panel *layout;
20841  const struct nk_input *in;
20842  const struct nk_style *style;
20843 
20844  enum nk_widget_layout_states state;
20845  struct nk_rect bounds;
20846 
20847  NK_ASSERT(ctx);
20848  NK_ASSERT(value);
20849  NK_ASSERT(ctx->current);
20850  NK_ASSERT(ctx->current->layout);
20851  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20852  return 0;
20853 
20854  win = ctx->current;
20855  layout = win->layout;
20856  style = &ctx->style;
20857 
20858  state = nk_widget(&bounds, ctx);
20859  if (!state) return 0;
20860  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20861  return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20862  str, len, align, value, &style->selectable, in, style->font);
20863 }
20864 
20865 NK_API int
20866 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img,
20867  const char *str, int len, nk_flags align, int *value)
20868 {
20869  struct nk_window *win;
20870  struct nk_panel *layout;
20871  const struct nk_input *in;
20872  const struct nk_style *style;
20873 
20874  enum nk_widget_layout_states state;
20875  struct nk_rect bounds;
20876 
20877  NK_ASSERT(ctx);
20878  NK_ASSERT(value);
20879  NK_ASSERT(ctx->current);
20880  NK_ASSERT(ctx->current->layout);
20881  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20882  return 0;
20883 
20884  win = ctx->current;
20885  layout = win->layout;
20886  style = &ctx->style;
20887 
20888  state = nk_widget(&bounds, ctx);
20889  if (!state) return 0;
20890  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20891  return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20892  str, len, align, value, &img, &style->selectable, in, style->font);
20893 }
20894 
20895 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20896  nk_flags align, int value)
20897 {nk_selectable_text(ctx, str, len, align, &value);return value;}
20898 
20899 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20900 {return nk_selectable_text(ctx, str, nk_strlen(str), align, value);}
20901 
20902 NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img,
20903  const char *str, nk_flags align, int *value)
20904 {return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);}
20905 
20906 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20907 {nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;}
20908 
20909 NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img,
20910  const char *str, nk_flags align, int value)
20911 {nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;}
20912 
20913 NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img,
20914  const char *str, int len, nk_flags align, int value)
20915 {nk_selectable_image_text(ctx, img, str, len, align, &value);return value;}
20916 
20917 /*----------------------------------------------------------------
20918  *
20919  * CHECKBOX
20920  *
20921  * --------------------------------------------------------------*/
20922 NK_API int
20923 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20924 {
20925  struct nk_window *win;
20926  struct nk_panel *layout;
20927  const struct nk_input *in;
20928  const struct nk_style *style;
20929 
20930  struct nk_rect bounds;
20931  enum nk_widget_layout_states state;
20932 
20933  NK_ASSERT(ctx);
20934  NK_ASSERT(ctx->current);
20935  NK_ASSERT(ctx->current->layout);
20936  if (!ctx || !ctx->current || !ctx->current->layout)
20937  return active;
20938 
20939  win = ctx->current;
20940  style = &ctx->style;
20941  layout = win->layout;
20942 
20943  state = nk_widget(&bounds, ctx);
20944  if (!state) return active;
20945  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20946  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20947  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20948  return active;
20949 }
20950 
20951 NK_API unsigned int
20952 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20953  unsigned int flags, unsigned int value)
20954 {
20955  int old_active;
20956  NK_ASSERT(ctx);
20957  NK_ASSERT(text);
20958  if (!ctx || !text) return flags;
20959  old_active = (int)((flags & value) & value);
20960  if (nk_check_text(ctx, text, len, old_active))
20961  flags |= value;
20962  else flags &= ~value;
20963  return flags;
20964 }
20965 
20966 NK_API int
20967 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20968 {
20969  int old_val;
20970  NK_ASSERT(ctx);
20971  NK_ASSERT(text);
20972  NK_ASSERT(active);
20973  if (!ctx || !text || !active) return 0;
20974  old_val = *active;
20975  *active = nk_check_text(ctx, text, len, *active);
20976  return old_val != *active;
20977 }
20978 
20979 NK_API int
20980 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20981  unsigned int *flags, unsigned int value)
20982 {
20983  int active;
20984  NK_ASSERT(ctx);
20985  NK_ASSERT(text);
20986  NK_ASSERT(flags);
20987  if (!ctx || !text || !flags) return 0;
20988 
20989  active = (int)((*flags & value) & value);
20990  if (nk_checkbox_text(ctx, text, len, &active)) {
20991  if (active) *flags |= value;
20992  else *flags &= ~value;
20993  return 1;
20994  }
20995  return 0;
20996 }
20997 
20998 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
20999 {return nk_check_text(ctx, label, nk_strlen(label), active);}
21000 
21001 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
21002  unsigned int flags, unsigned int value)
21003 {return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);}
21004 
21005 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
21006 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);}
21007 
21008 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
21009  unsigned int *flags, unsigned int value)
21010 {return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);}
21011 
21012 /*----------------------------------------------------------------
21013  *
21014  * OPTION
21015  *
21016  * --------------------------------------------------------------*/
21017 NK_API int
21018 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
21019 {
21020  struct nk_window *win;
21021  struct nk_panel *layout;
21022  const struct nk_input *in;
21023  const struct nk_style *style;
21024 
21025  struct nk_rect bounds;
21026  enum nk_widget_layout_states state;
21027 
21028  NK_ASSERT(ctx);
21029  NK_ASSERT(ctx->current);
21030  NK_ASSERT(ctx->current->layout);
21031  if (!ctx || !ctx->current || !ctx->current->layout)
21032  return is_active;
21033 
21034  win = ctx->current;
21035  style = &ctx->style;
21036  layout = win->layout;
21037 
21038  state = nk_widget(&bounds, ctx);
21039  if (!state) return state;
21040  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21041  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
21042  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
21043  return is_active;
21044 }
21045 
21046 NK_API int
21047 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
21048 {
21049  int old_value;
21050  NK_ASSERT(ctx);
21051  NK_ASSERT(text);
21052  NK_ASSERT(active);
21053  if (!ctx || !text || !active) return 0;
21054  old_value = *active;
21055  *active = nk_option_text(ctx, text, len, old_value);
21056  return old_value != *active;
21057 }
21058 
21059 NK_API int
21060 nk_option_label(struct nk_context *ctx, const char *label, int active)
21061 {return nk_option_text(ctx, label, nk_strlen(label), active);}
21062 
21063 NK_API int
21064 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
21065 {return nk_radio_text(ctx, label, nk_strlen(label), active);}
21066 
21067 /*----------------------------------------------------------------
21068  *
21069  * SLIDER
21070  *
21071  * --------------------------------------------------------------*/
21072 NK_API int
21073 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
21074  float value_step)
21075 {
21076  struct nk_window *win;
21077  struct nk_panel *layout;
21078  struct nk_input *in;
21079  const struct nk_style *style;
21080 
21081  int ret = 0;
21082  float old_value;
21083  struct nk_rect bounds;
21084  enum nk_widget_layout_states state;
21085 
21086  NK_ASSERT(ctx);
21087  NK_ASSERT(ctx->current);
21088  NK_ASSERT(ctx->current->layout);
21089  NK_ASSERT(value);
21090  if (!ctx || !ctx->current || !ctx->current->layout || !value)
21091  return ret;
21092 
21093  win = ctx->current;
21094  style = &ctx->style;
21095  layout = win->layout;
21096 
21097  state = nk_widget(&bounds, ctx);
21098  if (!state) return ret;
21099  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21100 
21101  old_value = *value;
21102  *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
21103  old_value, max_value, value_step, &style->slider, in, style->font);
21104  return (old_value > *value || old_value < *value);
21105 }
21106 
21107 NK_API float
21108 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
21109 {
21110  nk_slider_float(ctx, min, &val, max, step); return val;
21111 }
21112 
21113 NK_API int
21114 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
21115 {
21116  float value = (float)val;
21117  nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21118  return (int)value;
21119 }
21120 
21121 NK_API int
21122 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
21123 {
21124  int ret;
21125  float value = (float)*val;
21126  ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21127  *val = (int)value;
21128  return ret;
21129 }
21130 
21131 /*----------------------------------------------------------------
21132  *
21133  * PROGRESSBAR
21134  *
21135  * --------------------------------------------------------------*/
21136 NK_API int
21137 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
21138 {
21139  struct nk_window *win;
21140  struct nk_panel *layout;
21141  const struct nk_style *style;
21142  const struct nk_input *in;
21143 
21144  struct nk_rect bounds;
21145  enum nk_widget_layout_states state;
21146  nk_size old_value;
21147 
21148  NK_ASSERT(ctx);
21149  NK_ASSERT(cur);
21150  NK_ASSERT(ctx->current);
21151  NK_ASSERT(ctx->current->layout);
21152  if (!ctx || !ctx->current || !ctx->current->layout || !cur)
21153  return 0;
21154 
21155  win = ctx->current;
21156  style = &ctx->style;
21157  layout = win->layout;
21158  state = nk_widget(&bounds, ctx);
21159  if (!state) return 0;
21160 
21161  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21162  old_value = *cur;
21163  *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
21164  *cur, max, is_modifyable, &style->progress, in);
21165  return (*cur != old_value);
21166 }
21167 
21168 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
21169 {nk_progress(ctx, &cur, max, modifyable);return cur;}
21170 
21171 /*----------------------------------------------------------------
21172  *
21173  * EDIT
21174  *
21175  * --------------------------------------------------------------*/
21176 NK_API void
21177 nk_edit_focus(struct nk_context *ctx, nk_flags flags)
21178 {
21179  nk_hash hash;
21180  struct nk_window *win;
21181 
21182  NK_ASSERT(ctx);
21183  NK_ASSERT(ctx->current);
21184  if (!ctx || !ctx->current) return;
21185 
21186  win = ctx->current;
21187  hash = win->edit.seq;
21188  win->edit.active = nk_true;
21189  win->edit.name = hash;
21190  if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
21192 }
21193 
21194 NK_API void
21195 nk_edit_unfocus(struct nk_context *ctx)
21196 {
21197  struct nk_window *win;
21198  NK_ASSERT(ctx);
21199  NK_ASSERT(ctx->current);
21200  if (!ctx || !ctx->current) return;
21201 
21202  win = ctx->current;
21203  win->edit.active = nk_false;
21204  win->edit.name = 0;
21205 }
21206 
21207 NK_API nk_flags
21208 nk_edit_string(struct nk_context *ctx, nk_flags flags,
21209  char *memory, int *len, int max, nk_plugin_filter filter)
21210 {
21211  nk_hash hash;
21212  nk_flags state;
21213  struct nk_text_edit *edit;
21214  struct nk_window *win;
21215 
21216  NK_ASSERT(ctx);
21217  NK_ASSERT(memory);
21218  NK_ASSERT(len);
21219  if (!ctx || !memory || !len)
21220  return 0;
21221 
21222  filter = (!filter) ? nk_filter_default: filter;
21223  win = ctx->current;
21224  hash = win->edit.seq;
21225  edit = &ctx->text_edit;
21226  nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
21228 
21229  if (win->edit.active && hash == win->edit.name) {
21230  if (flags & NK_EDIT_NO_CURSOR)
21231  edit->cursor = nk_utf_len(memory, *len);
21232  else edit->cursor = win->edit.cursor;
21233  if (!(flags & NK_EDIT_SELECTABLE)) {
21234  edit->select_start = win->edit.cursor;
21235  edit->select_end = win->edit.cursor;
21236  } else {
21237  edit->select_start = win->edit.sel_start;
21238  edit->select_end = win->edit.sel_end;
21239  }
21240  edit->mode = win->edit.mode;
21241  edit->scrollbar.x = (float)win->edit.scrollbar.x;
21242  edit->scrollbar.y = (float)win->edit.scrollbar.y;
21243  edit->active = nk_true;
21244  } else edit->active = nk_false;
21245 
21246  max = NK_MAX(1, max);
21247  *len = NK_MIN(*len, max-1);
21248  nk_str_init_fixed(&edit->string, memory, (nk_size)max);
21249  edit->string.buffer.allocated = (nk_size)*len;
21250  edit->string.len = nk_utf_len(memory, *len);
21251  state = nk_edit_buffer(ctx, flags, edit, filter);
21252  *len = (int)edit->string.buffer.allocated;
21253 
21254  if (edit->active) {
21255  win->edit.cursor = edit->cursor;
21256  win->edit.sel_start = edit->select_start;
21257  win->edit.sel_end = edit->select_end;
21258  win->edit.mode = edit->mode;
21259  win->edit.scrollbar.x = (nk_ushort)edit->scrollbar.x;
21260  win->edit.scrollbar.y = (nk_ushort)edit->scrollbar.y;
21261  }
21262  return state;
21263 }
21264 
21265 NK_API nk_flags
21266 nk_edit_buffer(struct nk_context *ctx, nk_flags flags,
21267  struct nk_text_edit *edit, nk_plugin_filter filter)
21268 {
21269  struct nk_window *win;
21270  struct nk_style *style;
21271  struct nk_input *in;
21272 
21273  enum nk_widget_layout_states state;
21274  struct nk_rect bounds;
21275 
21276  nk_flags ret_flags = 0;
21277  unsigned char prev_state;
21278  nk_hash hash;
21279 
21280  /* make sure correct values */
21281  NK_ASSERT(ctx);
21282  NK_ASSERT(edit);
21283  NK_ASSERT(ctx->current);
21284  NK_ASSERT(ctx->current->layout);
21285  if (!ctx || !ctx->current || !ctx->current->layout)
21286  return 0;
21287 
21288  win = ctx->current;
21289  style = &ctx->style;
21290  state = nk_widget(&bounds, ctx);
21291  if (!state) return state;
21292  in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21293 
21294  /* check if edit is currently hot item */
21295  hash = win->edit.seq++;
21296  if (win->edit.active && hash == win->edit.name) {
21297  if (flags & NK_EDIT_NO_CURSOR)
21298  edit->cursor = edit->string.len;
21299  if (!(flags & NK_EDIT_SELECTABLE)) {
21300  edit->select_start = edit->cursor;
21301  edit->select_end = edit->cursor;
21302  }
21303  if (flags & NK_EDIT_CLIPBOARD)
21304  edit->clip = ctx->clip;
21305  }
21306 
21307  filter = (!filter) ? nk_filter_default: filter;
21308  prev_state = (unsigned char)edit->active;
21309  in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
21310  ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
21311  filter, edit, &style->edit, in, style->font);
21312 
21313  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
21315  if (edit->active && prev_state != edit->active) {
21316  /* current edit is now hot */
21317  win->edit.active = nk_true;
21318  win->edit.name = hash;
21319  } else if (prev_state && !edit->active) {
21320  /* current edit is now cold */
21321  win->edit.active = nk_false;
21322  }
21323  return ret_flags;
21324 }
21325 
21326 NK_API nk_flags
21327 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags,
21328  char *buffer, int max, nk_plugin_filter filter)
21329 {
21330  nk_flags result;
21331  int len = nk_strlen(buffer);
21332  result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
21333  buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
21334  return result;
21335 }
21336 
21337 /*----------------------------------------------------------------
21338  *
21339  * PROPERTY
21340  *
21341  * --------------------------------------------------------------*/
21342 NK_INTERN struct nk_property_variant
21343 nk_property_variant_int(int value, int min_value, int max_value, int step)
21344 {
21345  struct nk_property_variant result;
21346  result.kind = NK_PROPERTY_INT;
21347  result.value.i = value;
21348  result.min_value.i = min_value;
21349  result.max_value.i = max_value;
21350  result.step.i = step;
21351  return result;
21352 }
21353 
21354 NK_INTERN struct nk_property_variant
21355 nk_property_variant_float(float value, float min_value, float max_value, float step)
21356 {
21357  struct nk_property_variant result;
21358  result.kind = NK_PROPERTY_FLOAT;
21359  result.value.f = value;
21360  result.min_value.f = min_value;
21361  result.max_value.f = max_value;
21362  result.step.f = step;
21363  return result;
21364 }
21365 
21366 NK_INTERN struct nk_property_variant
21367 nk_property_variant_double(double value, double min_value, double max_value,
21368  double step)
21369 {
21370  struct nk_property_variant result;
21371  result.kind = NK_PROPERTY_DOUBLE;
21372  result.value.d = value;
21373  result.min_value.d = min_value;
21374  result.max_value.d = max_value;
21375  result.step.d = step;
21376  return result;
21377 }
21378 
21379 NK_INTERN void
21380 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
21381  float inc_per_pixel, const enum nk_property_filter filter)
21382 {
21383  struct nk_window *win;
21384  struct nk_panel *layout;
21385  struct nk_input *in;
21386  const struct nk_style *style;
21387 
21388  struct nk_rect bounds;
21389  enum nk_widget_layout_states s;
21390 
21391  int *state = 0;
21392  nk_hash hash = 0;
21393  char *buffer = 0;
21394  int *len = 0;
21395  int *cursor = 0;
21396  int *select_begin = 0;
21397  int *select_end = 0;
21398  int old_state;
21399 
21400  char dummy_buffer[NK_MAX_NUMBER_BUFFER];
21401  int dummy_state = NK_PROPERTY_DEFAULT;
21402  int dummy_length = 0;
21403  int dummy_cursor = 0;
21404  int dummy_select_begin = 0;
21405  int dummy_select_end = 0;
21406 
21407  NK_ASSERT(ctx);
21408  NK_ASSERT(ctx->current);
21409  NK_ASSERT(ctx->current->layout);
21410  if (!ctx || !ctx->current || !ctx->current->layout)
21411  return;
21412 
21413  win = ctx->current;
21414  layout = win->layout;
21415  style = &ctx->style;
21416  s = nk_widget(&bounds, ctx);
21417  if (!s) return;
21418 
21419  /* calculate hash from name */
21420  if (name[0] == '#') {
21421  hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
21422  name++; /* special number hash */
21423  } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
21424 
21425  /* check if property is currently hot item */
21426  if (win->property.active && hash == win->property.name) {
21427  buffer = win->property.buffer;
21428  len = &win->property.length;
21429  cursor = &win->property.cursor;
21430  state = &win->property.state;
21431  select_begin = &win->property.select_start;
21432  select_end = &win->property.select_end;
21433  } else {
21434  buffer = dummy_buffer;
21435  len = &dummy_length;
21436  cursor = &dummy_cursor;
21437  state = &dummy_state;
21438  select_begin = &dummy_select_begin;
21439  select_end = &dummy_select_end;
21440  }
21441 
21442  /* execute property widget */
21443  old_state = *state;
21444  ctx->text_edit.clip = ctx->clip;
21445  in = ((s == NK_WIDGET_ROM && !win->property.active) ||
21446  layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21447  nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
21448  variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
21449  select_end, &style->property, filter, in, style->font, &ctx->text_edit,
21450  ctx->button_behavior);
21451 
21452  if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
21453  /* current property is now hot */
21454  win->property.active = 1;
21455  NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
21456  win->property.length = *len;
21457  win->property.cursor = *cursor;
21458  win->property.state = *state;
21459  win->property.name = hash;
21460  win->property.select_start = *select_begin;
21461  win->property.select_end = *select_end;
21462  if (*state == NK_PROPERTY_DRAG) {
21463  ctx->input.mouse.grab = nk_true;
21464  ctx->input.mouse.grabbed = nk_true;
21465  }
21466  }
21467  /* check if previously active property is now inactive */
21468  if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
21469  if (old_state == NK_PROPERTY_DRAG) {
21470  ctx->input.mouse.grab = nk_false;
21471  ctx->input.mouse.grabbed = nk_false;
21472  ctx->input.mouse.ungrab = nk_true;
21473  }
21474  win->property.select_start = 0;
21475  win->property.select_end = 0;
21476  win->property.active = 0;
21477  }
21478 }
21479 
21480 NK_API void
21481 nk_property_int(struct nk_context *ctx, const char *name,
21482  int min, int *val, int max, int step, float inc_per_pixel)
21483 {
21484  struct nk_property_variant variant;
21485  NK_ASSERT(ctx);
21486  NK_ASSERT(name);
21487  NK_ASSERT(val);
21488 
21489  if (!ctx || !ctx->current || !name || !val) return;
21490  variant = nk_property_variant_int(*val, min, max, step);
21491  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21492  *val = variant.value.i;
21493 }
21494 
21495 NK_API void
21496 nk_property_float(struct nk_context *ctx, const char *name,
21497  float min, float *val, float max, float step, float inc_per_pixel)
21498 {
21499  struct nk_property_variant variant;
21500  NK_ASSERT(ctx);
21501  NK_ASSERT(name);
21502  NK_ASSERT(val);
21503 
21504  if (!ctx || !ctx->current || !name || !val) return;
21505  variant = nk_property_variant_float(*val, min, max, step);
21506  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21507  *val = variant.value.f;
21508 }
21509 
21510 NK_API void
21511 nk_property_double(struct nk_context *ctx, const char *name,
21512  double min, double *val, double max, double step, float inc_per_pixel)
21513 {
21514  struct nk_property_variant variant;
21515  NK_ASSERT(ctx);
21516  NK_ASSERT(name);
21517  NK_ASSERT(val);
21518 
21519  if (!ctx || !ctx->current || !name || !val) return;
21520  variant = nk_property_variant_double(*val, min, max, step);
21521  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21522  *val = variant.value.d;
21523 }
21524 
21525 NK_API int
21526 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
21527  int max, int step, float inc_per_pixel)
21528 {
21529  struct nk_property_variant variant;
21530  NK_ASSERT(ctx);
21531  NK_ASSERT(name);
21532 
21533  if (!ctx || !ctx->current || !name) return val;
21534  variant = nk_property_variant_int(val, min, max, step);
21535  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21536  val = variant.value.i;
21537  return val;
21538 }
21539 
21540 NK_API float
21541 nk_propertyf(struct nk_context *ctx, const char *name, float min,
21542  float val, float max, float step, float inc_per_pixel)
21543 {
21544  struct nk_property_variant variant;
21545  NK_ASSERT(ctx);
21546  NK_ASSERT(name);
21547 
21548  if (!ctx || !ctx->current || !name) return val;
21549  variant = nk_property_variant_float(val, min, max, step);
21550  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21551  val = variant.value.f;
21552  return val;
21553 }
21554 
21555 NK_API double
21556 nk_propertyd(struct nk_context *ctx, const char *name, double min,
21557  double val, double max, double step, float inc_per_pixel)
21558 {
21559  struct nk_property_variant variant;
21560  NK_ASSERT(ctx);
21561  NK_ASSERT(name);
21562 
21563  if (!ctx || !ctx->current || !name) return val;
21564  variant = nk_property_variant_double(val, min, max, step);
21565  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21566  val = variant.value.d;
21567  return val;
21568 }
21569 
21570 /*----------------------------------------------------------------
21571  *
21572  * COLOR PICKER
21573  *
21574  * --------------------------------------------------------------*/
21575 NK_API int
21576 nk_color_pick(struct nk_context * ctx, struct nk_color *color,
21577  enum nk_color_format fmt)
21578 {
21579  struct nk_window *win;
21580  struct nk_panel *layout;
21581  const struct nk_style *config;
21582  const struct nk_input *in;
21583 
21584  enum nk_widget_layout_states state;
21585  struct nk_rect bounds;
21586 
21587  NK_ASSERT(ctx);
21588  NK_ASSERT(color);
21589  NK_ASSERT(ctx->current);
21590  NK_ASSERT(ctx->current->layout);
21591  if (!ctx || !ctx->current || !ctx->current->layout || !color)
21592  return 0;
21593 
21594  win = ctx->current;
21595  config = &ctx->style;
21596  layout = win->layout;
21597  state = nk_widget(&bounds, ctx);
21598  if (!state) return 0;
21599  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21600  return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
21601  nk_vec2(0,0), in, config->font);
21602 }
21603 
21604 NK_API struct nk_color
21605 nk_color_picker(struct nk_context *ctx, struct nk_color color,
21606  enum nk_color_format fmt)
21607 {
21608  nk_color_pick(ctx, &color, fmt);
21609  return color;
21610 }
21611 
21612 /* -------------------------------------------------------------
21613  *
21614  * CHART
21615  *
21616  * --------------------------------------------------------------*/
21617 NK_API int
21618 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type,
21619  struct nk_color color, struct nk_color highlight,
21620  int count, float min_value, float max_value)
21621 {
21622  struct nk_window *win;
21623  struct nk_chart *chart;
21624  const struct nk_style *config;
21625  const struct nk_style_chart *style;
21626 
21627  const struct nk_style_item *background;
21628  struct nk_rect bounds = {0, 0, 0, 0};
21629 
21630  NK_ASSERT(ctx);
21631  NK_ASSERT(ctx->current);
21632  NK_ASSERT(ctx->current->layout);
21633 
21634  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
21635  if (!nk_widget(&bounds, ctx)) {
21636  chart = &ctx->current->layout->chart;
21637  nk_zero(chart, sizeof(*chart));
21638  return 0;
21639  }
21640 
21641  win = ctx->current;
21642  config = &ctx->style;
21643  chart = &win->layout->chart;
21644  style = &config->chart;
21645 
21646  /* setup basic generic chart */
21647  nk_zero(chart, sizeof(*chart));
21648  chart->x = bounds.x + style->padding.x;
21649  chart->y = bounds.y + style->padding.y;
21650  chart->w = bounds.w - 2 * style->padding.x;
21651  chart->h = bounds.h - 2 * style->padding.y;
21652  chart->w = NK_MAX(chart->w, 2 * style->padding.x);
21653  chart->h = NK_MAX(chart->h, 2 * style->padding.y);
21654 
21655  /* add first slot into chart */
21656  {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21657  slot->type = type;
21658  slot->count = count;
21659  slot->color = color;
21660  slot->highlight = highlight;
21661  slot->min = NK_MIN(min_value, max_value);
21662  slot->max = NK_MAX(min_value, max_value);
21663  slot->range = slot->max - slot->min;}
21664 
21665  /* draw chart background */
21666  background = &style->background;
21667  if (background->type == NK_STYLE_ITEM_IMAGE) {
21668  nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
21669  } else {
21670  nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
21671  nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
21672  style->rounding, style->background.data.color);
21673  }
21674  return 1;
21675 }
21676 
21677 NK_API int
21678 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
21679  int count, float min_value, float max_value)
21680 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21681 
21682 NK_API void
21683 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type,
21684  struct nk_color color, struct nk_color highlight,
21685  int count, float min_value, float max_value)
21686 {
21687  NK_ASSERT(ctx);
21688  NK_ASSERT(ctx->current);
21689  NK_ASSERT(ctx->current->layout);
21690  NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
21691  if (!ctx || !ctx->current || !ctx->current->layout) return;
21692  if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
21693 
21694  /* add another slot into the graph */
21695  {struct nk_chart *chart = &ctx->current->layout->chart;
21696  struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21697  slot->type = type;
21698  slot->count = count;
21699  slot->color = color;
21700  slot->highlight = highlight;
21701  slot->min = NK_MIN(min_value, max_value);
21702  slot->max = NK_MAX(min_value, max_value);
21703  slot->range = slot->max - slot->min;}
21704 }
21705 
21706 NK_API void
21707 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
21708  int count, float min_value, float max_value)
21709 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21710 
21711 NK_INTERN nk_flags
21712 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
21713  struct nk_chart *g, float value, int slot)
21714 {
21715  struct nk_panel *layout = win->layout;
21716  const struct nk_input *i = &ctx->input;
21717  struct nk_command_buffer *out = &win->buffer;
21718 
21719  nk_flags ret = 0;
21720  struct nk_vec2 cur;
21721  struct nk_rect bounds;
21722  struct nk_color color;
21723  float step;
21724  float range;
21725  float ratio;
21726 
21727  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21728  step = g->w / (float)g->slots[slot].count;
21729  range = g->slots[slot].max - g->slots[slot].min;
21730  ratio = (value - g->slots[slot].min) / range;
21731 
21732  if (g->slots[slot].index == 0) {
21733  /* first data point does not have a connection */
21734  g->slots[slot].last.x = g->x;
21735  g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
21736 
21737  bounds.x = g->slots[slot].last.x - 2;
21738  bounds.y = g->slots[slot].last.y - 2;
21739  bounds.w = bounds.h = 4;
21740 
21741  color = g->slots[slot].color;
21742  if (!(layout->flags & NK_WINDOW_ROM) &&
21743  NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
21744  ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
21745  ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
21747  color = g->slots[slot].highlight;
21748  }
21749  nk_fill_rect(out, bounds, 0, color);
21750  g->slots[slot].index += 1;
21751  return ret;
21752  }
21753 
21754  /* draw a line between the last data point and the new one */
21755  color = g->slots[slot].color;
21756  cur.x = g->x + (float)(step * (float)g->slots[slot].index);
21757  cur.y = (g->y + g->h) - (ratio * (float)g->h);
21758  nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
21759 
21760  bounds.x = cur.x - 3;
21761  bounds.y = cur.y - 3;
21762  bounds.w = bounds.h = 6;
21763 
21764  /* user selection of current data point */
21765  if (!(layout->flags & NK_WINDOW_ROM)) {
21766  if (nk_input_is_mouse_hovering_rect(i, bounds)) {
21767  ret = NK_CHART_HOVERING;
21768  ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
21770  color = g->slots[slot].highlight;
21771  }
21772  }
21773  nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
21774 
21775  /* save current data point position */
21776  g->slots[slot].last.x = cur.x;
21777  g->slots[slot].last.y = cur.y;
21778  g->slots[slot].index += 1;
21779  return ret;
21780 }
21781 
21782 NK_INTERN nk_flags
21783 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
21784  struct nk_chart *chart, float value, int slot)
21785 {
21786  struct nk_command_buffer *out = &win->buffer;
21787  const struct nk_input *in = &ctx->input;
21788  struct nk_panel *layout = win->layout;
21789 
21790  float ratio;
21791  nk_flags ret = 0;
21792  struct nk_color color;
21793  struct nk_rect item = {0,0,0,0};
21794 
21795  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21796  if (chart->slots[slot].index >= chart->slots[slot].count)
21797  return nk_false;
21798  if (chart->slots[slot].count) {
21799  float padding = (float)(chart->slots[slot].count-1);
21800  item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
21801  }
21802 
21803  /* calculate bounds of current bar chart entry */
21804  color = chart->slots[slot].color;;
21805  item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
21806  if (value >= 0) {
21807  ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
21808  item.y = (chart->y + chart->h) - chart->h * ratio;
21809  } else {
21810  ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
21811  item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
21812  }
21813  item.x = chart->x + ((float)chart->slots[slot].index * item.w);
21814  item.x = item.x + ((float)chart->slots[slot].index);
21815 
21816  /* user chart bar selection */
21817  if (!(layout->flags & NK_WINDOW_ROM) &&
21818  NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
21819  ret = NK_CHART_HOVERING;
21820  ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
21822  color = chart->slots[slot].highlight;
21823  }
21824  nk_fill_rect(out, item, 0, color);
21825  chart->slots[slot].index += 1;
21826  return ret;
21827 }
21828 
21829 NK_API nk_flags
21830 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
21831 {
21832  nk_flags flags;
21833  struct nk_window *win;
21834 
21835  NK_ASSERT(ctx);
21836  NK_ASSERT(ctx->current);
21837  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21838  NK_ASSERT(slot < ctx->current->layout->chart.slot);
21839  if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
21840  if (slot >= ctx->current->layout->chart.slot) return nk_false;
21841 
21842  win = ctx->current;
21843  if (win->layout->chart.slot < slot) return nk_false;
21844  switch (win->layout->chart.slots[slot].type) {
21845  case NK_CHART_LINES:
21846  flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
21847  case NK_CHART_COLUMN:
21848  flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
21849  default:
21850  case NK_CHART_MAX:
21851  flags = 0;
21852  }
21853  return flags;
21854 }
21855 
21856 NK_API nk_flags
21857 nk_chart_push(struct nk_context *ctx, float value)
21858 {return nk_chart_push_slot(ctx, value, 0);}
21859 
21860 NK_API void
21861 nk_chart_end(struct nk_context *ctx)
21862 {
21863  struct nk_window *win;
21864  struct nk_chart *chart;
21865 
21866  NK_ASSERT(ctx);
21867  NK_ASSERT(ctx->current);
21868  if (!ctx || !ctx->current)
21869  return;
21870 
21871  win = ctx->current;
21872  chart = &win->layout->chart;
21873  NK_MEMSET(chart, 0, sizeof(*chart));
21874  return;
21875 }
21876 
21877 NK_API void
21878 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
21879  int count, int offset)
21880 {
21881  int i = 0;
21882  float min_value;
21883  float max_value;
21884 
21885  NK_ASSERT(ctx);
21886  NK_ASSERT(values);
21887  if (!ctx || !values || !count) return;
21888 
21889  min_value = values[offset];
21890  max_value = values[offset];
21891  for (i = 0; i < count; ++i) {
21892  min_value = NK_MIN(values[i + offset], min_value);
21893  max_value = NK_MAX(values[i + offset], max_value);
21894  }
21895 
21896  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
21897  for (i = 0; i < count; ++i)
21898  nk_chart_push(ctx, values[i + offset]);
21899  nk_chart_end(ctx);
21900  }
21901 }
21902 
21903 NK_API void
21904 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
21905  float(*value_getter)(void* user, int index), int count, int offset)
21906 {
21907  int i = 0;
21908  float min_value;
21909  float max_value;
21910 
21911  NK_ASSERT(ctx);
21912  NK_ASSERT(value_getter);
21913  if (!ctx || !value_getter || !count) return;
21914 
21915  max_value = min_value = value_getter(userdata, offset);
21916  for (i = 0; i < count; ++i) {
21917  float value = value_getter(userdata, i + offset);
21918  min_value = NK_MIN(value, min_value);
21919  max_value = NK_MAX(value, max_value);
21920  }
21921 
21922  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
21923  for (i = 0; i < count; ++i)
21924  nk_chart_push(ctx, value_getter(userdata, i + offset));
21925  nk_chart_end(ctx);
21926  }
21927 }
21928 
21929 /* -------------------------------------------------------------
21930  *
21931  * GROUP
21932  *
21933  * --------------------------------------------------------------*/
21934 NK_API int
21936  nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
21937 {
21938  struct nk_rect bounds;
21939  struct nk_window panel;
21940  struct nk_window *win;
21941 
21942  win = ctx->current;
21943  nk_panel_alloc_space(&bounds, ctx);
21944  {const struct nk_rect *c = &win->layout->clip;
21945  if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
21946  !(flags & NK_WINDOW_MOVABLE)) {
21947  return 0;
21948  }}
21949  if (win->flags & NK_WINDOW_ROM)
21950  flags |= NK_WINDOW_ROM;
21951 
21952  /* initialize a fake window to create the panel from */
21953  nk_zero(&panel, sizeof(panel));
21954  panel.bounds = bounds;
21955  panel.flags = flags;
21956  panel.scrollbar.x = *x_offset;
21957  panel.scrollbar.y = *y_offset;
21958  panel.buffer = win->buffer;
21959  panel.layout = (struct nk_panel*)nk_create_panel(ctx);
21960  ctx->current = &panel;
21961  nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
21962 
21963  win->buffer = panel.buffer;
21964  win->buffer.clip = panel.layout->clip;
21965  panel.layout->offset_x = x_offset;
21966  panel.layout->offset_y = y_offset;
21967  panel.layout->parent = win->layout;
21968  win->layout = panel.layout;
21969 
21970  ctx->current = win;
21971  if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
21972  (panel.layout->flags & NK_WINDOW_MINIMIZED))
21973  {
21974  nk_flags f = panel.layout->flags;
21975  nk_group_scrolled_end(ctx);
21976  if (f & NK_WINDOW_CLOSED)
21977  return NK_WINDOW_CLOSED;
21978  if (f & NK_WINDOW_MINIMIZED)
21979  return NK_WINDOW_MINIMIZED;
21980  }
21981  return 1;
21982 }
21983 
21984 NK_API void
21985 nk_group_scrolled_end(struct nk_context *ctx)
21986 {
21987  struct nk_window *win;
21988  struct nk_panel *parent;
21989  struct nk_panel *g;
21990 
21991  struct nk_rect clip;
21992  struct nk_window pan;
21993  struct nk_vec2 panel_padding;
21994 
21995  NK_ASSERT(ctx);
21996  NK_ASSERT(ctx->current);
21997  if (!ctx || !ctx->current)
21998  return;
21999 
22000  /* make sure nk_group_begin was called correctly */
22001  NK_ASSERT(ctx->current);
22002  win = ctx->current;
22003  NK_ASSERT(win->layout);
22004  g = win->layout;
22005  NK_ASSERT(g->parent);
22006  parent = g->parent;
22007 
22008  /* dummy window */
22009  nk_zero_struct(pan);
22010  panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
22011  pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
22012  pan.bounds.x = g->bounds.x - panel_padding.x;
22013  pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
22014  pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
22015  if (g->flags & NK_WINDOW_BORDER) {
22016  pan.bounds.x -= g->border;
22017  pan.bounds.y -= g->border;
22018  pan.bounds.w += 2*g->border;
22019  pan.bounds.h += 2*g->border;
22020  }
22021  if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
22022  pan.bounds.w += ctx->style.window.scrollbar_size.x;
22023  pan.bounds.h += ctx->style.window.scrollbar_size.y;
22024  }
22025  pan.scrollbar.x = *g->offset_x;
22026  pan.scrollbar.y = *g->offset_y;
22027  pan.flags = g->flags;
22028  pan.buffer = win->buffer;
22029  pan.layout = g;
22030  pan.parent = win;
22031  ctx->current = &pan;
22032 
22033  /* make sure group has correct clipping rectangle */
22034  nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
22035  pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
22036  nk_push_scissor(&pan.buffer, clip);
22037  nk_end(ctx);
22038 
22039  win->buffer = pan.buffer;
22040  nk_push_scissor(&win->buffer, parent->clip);
22041  ctx->current = win;
22042  win->layout = parent;
22043  g->bounds = pan.bounds;
22044  return;
22045 }
22046 
22047 NK_API int
22049  struct nk_scroll *scroll, const char *title, nk_flags flags)
22050 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);}
22051 
22052 NK_API int
22053 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
22054 {
22055  int title_len;
22056  nk_hash title_hash;
22057  struct nk_window *win;
22058  nk_uint *x_offset;
22059  nk_uint *y_offset;
22060 
22061  NK_ASSERT(ctx);
22062  NK_ASSERT(title);
22063  NK_ASSERT(ctx->current);
22064  NK_ASSERT(ctx->current->layout);
22065  if (!ctx || !ctx->current || !ctx->current->layout || !title)
22066  return 0;
22067 
22068  /* find persistent group scrollbar value */
22069  win = ctx->current;
22070  title_len = (int)nk_strlen(title);
22071  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
22072  x_offset = nk_find_value(win, title_hash);
22073  if (!x_offset) {
22074  x_offset = nk_add_value(ctx, win, title_hash, 0);
22075  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
22076 
22077  NK_ASSERT(x_offset);
22078  NK_ASSERT(y_offset);
22079  if (!x_offset || !y_offset) return 0;
22080  *x_offset = *y_offset = 0;
22081  } else y_offset = nk_find_value(win, title_hash+1);
22082  return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
22083 }
22084 
22085 NK_API void
22086 nk_group_end(struct nk_context *ctx)
22087 {nk_group_scrolled_end(ctx);}
22088 
22089 NK_API int
22090 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
22091  const char *title, nk_flags flags, int row_height, int row_count)
22092 {
22093  int title_len;
22094  nk_hash title_hash;
22095  nk_uint *x_offset;
22096  nk_uint *y_offset;
22097 
22098  int result;
22099  struct nk_window *win;
22100  struct nk_panel *layout;
22101  const struct nk_style *style;
22102  struct nk_vec2 item_spacing;
22103 
22104  NK_ASSERT(ctx);
22105  NK_ASSERT(view);
22106  NK_ASSERT(title);
22107  if (!ctx || !view || !title) return 0;
22108 
22109  win = ctx->current;
22110  style = &ctx->style;
22111  item_spacing = style->window.spacing;
22112  row_height += NK_MAX(0, (int)item_spacing.y);
22113 
22114  /* find persistent list view scrollbar offset */
22115  title_len = (int)nk_strlen(title);
22116  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
22117  x_offset = nk_find_value(win, title_hash);
22118  if (!x_offset) {
22119  x_offset = nk_add_value(ctx, win, title_hash, 0);
22120  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
22121 
22122  NK_ASSERT(x_offset);
22123  NK_ASSERT(y_offset);
22124  if (!x_offset || !y_offset) return 0;
22125  *x_offset = *y_offset = 0;
22126  } else y_offset = nk_find_value(win, title_hash+1);
22127  view->scroll_value = *y_offset;
22128  view->scroll_pointer = y_offset;
22129 
22130  *y_offset = 0;
22131  result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
22132  win = ctx->current;
22133  layout = win->layout;
22134 
22135  view->total_height = row_height * NK_MAX(row_count,1);
22136  view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
22137  view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
22138  view->end = view->begin + view->count;
22139  view->ctx = ctx;
22140  return result;
22141 }
22142 
22143 NK_API void
22144 nk_list_view_end(struct nk_list_view *view)
22145 {
22146  struct nk_context *ctx;
22147  struct nk_window *win;
22148  struct nk_panel *layout;
22149 
22150  NK_ASSERT(view);
22151  NK_ASSERT(view->ctx);
22152  NK_ASSERT(view->scroll_pointer);
22153  if (!view || !view->ctx) return;
22154 
22155  ctx = view->ctx;
22156  win = ctx->current;
22157  layout = win->layout;
22158  layout->at_y = layout->bounds.y + (float)view->total_height;
22159  *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
22160  nk_group_end(view->ctx);
22161 }
22162 
22163 /* --------------------------------------------------------------
22164  *
22165  * POPUP
22166  *
22167  * --------------------------------------------------------------*/
22168 NK_API int
22169 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type,
22170  const char *title, nk_flags flags, struct nk_rect rect)
22171 {
22172  struct nk_window *popup;
22173  struct nk_window *win;
22174  struct nk_panel *panel;
22175 
22176  int title_len;
22177  nk_hash title_hash;
22178  nk_size allocated;
22179 
22180  NK_ASSERT(ctx);
22181  NK_ASSERT(title);
22182  NK_ASSERT(ctx->current);
22183  NK_ASSERT(ctx->current->layout);
22184  if (!ctx || !ctx->current || !ctx->current->layout)
22185  return 0;
22186 
22187  win = ctx->current;
22188  panel = win->layout;
22189  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
22190  (void)panel;
22191  title_len = (int)nk_strlen(title);
22192  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
22193 
22194  popup = win->popup.win;
22195  if (!popup) {
22196  popup = (struct nk_window*)nk_create_window(ctx);
22197  popup->parent = win;
22198  win->popup.win = popup;
22199  win->popup.active = 0;
22200  win->popup.type = NK_PANEL_POPUP;
22201  }
22202 
22203  /* make sure we have correct popup */
22204  if (win->popup.name != title_hash) {
22205  if (!win->popup.active) {
22206  nk_zero(popup, sizeof(*popup));
22207  win->popup.name = title_hash;
22208  win->popup.active = 1;
22209  win->popup.type = NK_PANEL_POPUP;
22210  } else return 0;
22211  }
22212 
22213  /* popup position is local to window */
22214  ctx->current = popup;
22215  rect.x += win->layout->clip.x;
22216  rect.y += win->layout->clip.y;
22217 
22218  /* setup popup data */
22219  popup->parent = win;
22220  popup->bounds = rect;
22221  popup->seq = ctx->seq;
22222  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22223  popup->flags = flags;
22224  popup->flags |= NK_WINDOW_BORDER;
22225  if (type == NK_POPUP_DYNAMIC)
22226  popup->flags |= NK_WINDOW_DYNAMIC;
22227 
22228  popup->buffer = win->buffer;
22229  nk_start_popup(ctx, win);
22230  allocated = ctx->memory.allocated;
22231  nk_push_scissor(&popup->buffer, nk_null_rect);
22232 
22233  if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
22234  /* popup is running therefore invalidate parent panels */
22235  struct nk_panel *root;
22236  root = win->layout;
22237  while (root) {
22238  root->flags |= NK_WINDOW_ROM;
22239  root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
22240  root = root->parent;
22241  }
22242  win->popup.active = 1;
22243  popup->layout->offset_x = &popup->scrollbar.x;
22244  popup->layout->offset_y = &popup->scrollbar.y;
22245  popup->layout->parent = win->layout;
22246  return 1;
22247  } else {
22248  /* popup was closed/is invalid so cleanup */
22249  struct nk_panel *root;
22250  root = win->layout;
22251  while (root) {
22252  root->flags |= NK_WINDOW_REMOVE_ROM;
22253  root = root->parent;
22254  }
22255  win->popup.buf.active = 0;
22256  win->popup.active = 0;
22257  ctx->memory.allocated = allocated;
22258  ctx->current = win;
22259  nk_free_panel(ctx, popup->layout);
22260  popup->layout = 0;
22261  return 0;
22262  }
22263 }
22264 
22265 NK_INTERN int
22266 nk_nonblock_begin(struct nk_context *ctx,
22267  nk_flags flags, struct nk_rect body, struct nk_rect header,
22268  enum nk_panel_type panel_type)
22269 {
22270  struct nk_window *popup;
22271  struct nk_window *win;
22272  struct nk_panel *panel;
22273  int is_active = nk_true;
22274 
22275  NK_ASSERT(ctx);
22276  NK_ASSERT(ctx->current);
22277  NK_ASSERT(ctx->current->layout);
22278  if (!ctx || !ctx->current || !ctx->current->layout)
22279  return 0;
22280 
22281  /* popups cannot have popups */
22282  win = ctx->current;
22283  panel = win->layout;
22284  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
22285  (void)panel;
22286  popup = win->popup.win;
22287  if (!popup) {
22288  /* create window for nonblocking popup */
22289  popup = (struct nk_window*)nk_create_window(ctx);
22290  popup->parent = win;
22291  win->popup.win = popup;
22292  win->popup.type = panel_type;
22293  nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
22294  } else {
22295  /* close the popup if user pressed outside or in the header */
22296  int pressed, in_body, in_header;
22298  in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22299  in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
22300  if (pressed && (!in_body || in_header))
22301  is_active = nk_false;
22302  }
22303  win->popup.header = header;
22304 
22305  if (!is_active) {
22306  /* remove read only mode from all parent panels */
22307  struct nk_panel *root = win->layout;
22308  while (root) {
22309  root->flags |= NK_WINDOW_REMOVE_ROM;
22310  root = root->parent;
22311  }
22312  return is_active;
22313  }
22314 
22315  popup->bounds = body;
22316  popup->parent = win;
22317  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22318  popup->flags = flags;
22319  popup->flags |= NK_WINDOW_BORDER;
22320  popup->flags |= NK_WINDOW_DYNAMIC;
22321  popup->seq = ctx->seq;
22322  win->popup.active = 1;
22323  NK_ASSERT(popup->layout);
22324 
22325  nk_start_popup(ctx, win);
22326  popup->buffer = win->buffer;
22327  nk_push_scissor(&popup->buffer, nk_null_rect);
22328  ctx->current = popup;
22329 
22330  nk_panel_begin(ctx, 0, panel_type);
22331  win->buffer = popup->buffer;
22332  popup->layout->parent = win->layout;
22333  popup->layout->offset_x = &popup->scrollbar.x;
22334  popup->layout->offset_y = &popup->scrollbar.y;
22335 
22336  /* set read only mode to all parent panels */
22337  {struct nk_panel *root;
22338  root = win->layout;
22339  while (root) {
22340  root->flags |= NK_WINDOW_ROM;
22341  root = root->parent;
22342  }}
22343  return is_active;
22344 }
22345 
22346 NK_API void
22347 nk_popup_close(struct nk_context *ctx)
22348 {
22349  struct nk_window *popup;
22350  NK_ASSERT(ctx);
22351  if (!ctx || !ctx->current) return;
22352 
22353  popup = ctx->current;
22354  NK_ASSERT(popup->parent);
22355  NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
22356  popup->flags |= NK_WINDOW_HIDDEN;
22357 }
22358 
22359 NK_API void
22360 nk_popup_end(struct nk_context *ctx)
22361 {
22362  struct nk_window *win;
22363  struct nk_window *popup;
22364 
22365  NK_ASSERT(ctx);
22366  NK_ASSERT(ctx->current);
22367  NK_ASSERT(ctx->current->layout);
22368  if (!ctx || !ctx->current || !ctx->current->layout)
22369  return;
22370 
22371  popup = ctx->current;
22372  if (!popup->parent) return;
22373  win = popup->parent;
22374  if (popup->flags & NK_WINDOW_HIDDEN) {
22375  struct nk_panel *root;
22376  root = win->layout;
22377  while (root) {
22378  root->flags |= NK_WINDOW_REMOVE_ROM;
22379  root = root->parent;
22380  }
22381  win->popup.active = 0;
22382  }
22383  nk_push_scissor(&popup->buffer, nk_null_rect);
22384  nk_end(ctx);
22385 
22386  win->buffer = popup->buffer;
22387  nk_finish_popup(ctx, win);
22388  ctx->current = win;
22389  nk_push_scissor(&win->buffer, win->layout->clip);
22390 }
22391 /* -------------------------------------------------------------
22392  *
22393  * TOOLTIP
22394  *
22395  * -------------------------------------------------------------- */
22396 NK_API int
22397 nk_tooltip_begin(struct nk_context *ctx, float width)
22398 {
22399  struct nk_window *win;
22400  const struct nk_input *in;
22401  struct nk_rect bounds;
22402  int ret;
22403 
22404  NK_ASSERT(ctx);
22405  NK_ASSERT(ctx->current);
22406  NK_ASSERT(ctx->current->layout);
22407  if (!ctx || !ctx->current || !ctx->current->layout)
22408  return 0;
22409 
22410  /* make sure that no nonblocking popup is currently active */
22411  win = ctx->current;
22412  in = &ctx->input;
22413  if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
22414  return 0;
22415 
22416  bounds.w = width;
22417  bounds.h = nk_null_rect.h;
22418  bounds.x = (in->mouse.pos.x + 1) - win->layout->clip.x;
22419  bounds.y = (in->mouse.pos.y + 1) - win->layout->clip.y;
22420 
22421  ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC,
22422  "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
22423  if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
22424  win->popup.type = NK_PANEL_TOOLTIP;
22426  return ret;
22427 }
22428 
22429 NK_API void
22430 nk_tooltip_end(struct nk_context *ctx)
22431 {
22432  NK_ASSERT(ctx);
22433  NK_ASSERT(ctx->current);
22434  if (!ctx || !ctx->current) return;
22435  ctx->current->seq--;
22436  nk_popup_close(ctx);
22437  nk_popup_end(ctx);
22438 }
22439 
22440 NK_API void
22441 nk_tooltip(struct nk_context *ctx, const char *text)
22442 {
22443  const struct nk_style *style;
22444  struct nk_vec2 padding;
22445 
22446  int text_len;
22447  float text_width;
22448  float text_height;
22449 
22450  NK_ASSERT(ctx);
22451  NK_ASSERT(ctx->current);
22452  NK_ASSERT(ctx->current->layout);
22453  NK_ASSERT(text);
22454  if (!ctx || !ctx->current || !ctx->current->layout || !text)
22455  return;
22456 
22457  /* fetch configuration data */
22458  style = &ctx->style;
22459  padding = style->window.padding;
22460 
22461  /* calculate size of the text and tooltip */
22462  text_len = nk_strlen(text);
22463  text_width = style->font->width(style->font->userdata,
22464  style->font->height, text, text_len);
22465  text_width += (4 * padding.x);
22466  text_height = (style->font->height + 2 * padding.y);
22467 
22468  /* execute tooltip and fill with text */
22469  if (nk_tooltip_begin(ctx, (float)text_width)) {
22470  nk_layout_row_dynamic(ctx, (float)text_height, 1);
22471  nk_text(ctx, text, text_len, NK_TEXT_LEFT);
22472  nk_tooltip_end(ctx);
22473  }
22474 }
22475 /* -------------------------------------------------------------
22476  *
22477  * CONTEXTUAL
22478  *
22479  * -------------------------------------------------------------- */
22480 NK_API int
22481 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size,
22482  struct nk_rect trigger_bounds)
22483 {
22484  struct nk_window *win;
22485  struct nk_window *popup;
22486  struct nk_rect body;
22487 
22488  NK_STORAGE const struct nk_rect null_rect = {0,0,0,0};
22489  int is_clicked = 0;
22490  int is_active = 0;
22491  int is_open = 0;
22492  int ret = 0;
22493 
22494  NK_ASSERT(ctx);
22495  NK_ASSERT(ctx->current);
22496  NK_ASSERT(ctx->current->layout);
22497  if (!ctx || !ctx->current || !ctx->current->layout)
22498  return 0;
22499 
22500  win = ctx->current;
22501  ++win->popup.con_count;
22502 
22503  /* check if currently active contextual is active */
22504  popup = win->popup.win;
22505  is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
22506  is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
22507  if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
22508  return 0;
22509  if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked))
22510  return 0;
22511 
22512  /* calculate contextual position on click */
22513  win->popup.active_con = win->popup.con_count;
22514  if (is_clicked) {
22515  body.x = ctx->input.mouse.pos.x;
22516  body.y = ctx->input.mouse.pos.y;
22517  } else {
22518  body.x = popup->bounds.x;
22519  body.y = popup->bounds.y;
22520  }
22521  body.w = size.x;
22522  body.h = size.y;
22523 
22524  /* start nonblocking contextual popup */
22525  ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
22526  null_rect, NK_PANEL_CONTEXTUAL);
22527  if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
22528  else {
22529  win->popup.active_con = 0;
22530  if (win->popup.win)
22531  win->popup.win->flags = 0;
22532  }
22533  return ret;
22534 }
22535 
22536 NK_API int
22537 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
22538  nk_flags alignment)
22539 {
22540  struct nk_window *win;
22541  const struct nk_input *in;
22542  const struct nk_style *style;
22543 
22544  struct nk_rect bounds;
22545  enum nk_widget_layout_states state;
22546 
22547  NK_ASSERT(ctx);
22548  NK_ASSERT(ctx->current);
22549  NK_ASSERT(ctx->current->layout);
22550  if (!ctx || !ctx->current || !ctx->current->layout)
22551  return 0;
22552 
22553  win = ctx->current;
22554  style = &ctx->style;
22555  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22556  if (!state) return nk_false;
22557 
22558  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22559  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
22560  text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
22561  nk_contextual_close(ctx);
22562  return nk_true;
22563  }
22564  return nk_false;
22565 }
22566 
22567 NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align)
22568 {return nk_contextual_item_text(ctx, label, nk_strlen(label), align);}
22569 
22570 NK_API int
22571 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img,
22572  const char *text, int len, nk_flags align)
22573 {
22574  struct nk_window *win;
22575  const struct nk_input *in;
22576  const struct nk_style *style;
22577 
22578  struct nk_rect bounds;
22579  enum nk_widget_layout_states state;
22580 
22581  NK_ASSERT(ctx);
22582  NK_ASSERT(ctx->current);
22583  NK_ASSERT(ctx->current->layout);
22584  if (!ctx || !ctx->current || !ctx->current->layout)
22585  return 0;
22586 
22587  win = ctx->current;
22588  style = &ctx->style;
22589  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22590  if (!state) return nk_false;
22591 
22592  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22593  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
22594  img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
22595  nk_contextual_close(ctx);
22596  return nk_true;
22597  }
22598  return nk_false;
22599 }
22600 
22601 NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img,
22602  const char *label, nk_flags align)
22603 {return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);}
22604 
22605 NK_API int
22607  const char *text, int len, nk_flags align)
22608 {
22609  struct nk_window *win;
22610  const struct nk_input *in;
22611  const struct nk_style *style;
22612 
22613  struct nk_rect bounds;
22614  enum nk_widget_layout_states state;
22615 
22616  NK_ASSERT(ctx);
22617  NK_ASSERT(ctx->current);
22618  NK_ASSERT(ctx->current->layout);
22619  if (!ctx || !ctx->current || !ctx->current->layout)
22620  return 0;
22621 
22622  win = ctx->current;
22623  style = &ctx->style;
22624  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22625  if (!state) return nk_false;
22626 
22627  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22628  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22629  symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
22630  nk_contextual_close(ctx);
22631  return nk_true;
22632  }
22633  return nk_false;
22634 }
22635 
22637  const char *text, nk_flags align)
22638 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);}
22639 
22640 NK_API void
22641 nk_contextual_close(struct nk_context *ctx)
22642 {
22643  NK_ASSERT(ctx);
22644  NK_ASSERT(ctx->current);
22645  NK_ASSERT(ctx->current->layout);
22646  if (!ctx || !ctx->current || !ctx->current->layout) return;
22647  nk_popup_close(ctx);
22648 }
22649 
22650 NK_API void
22651 nk_contextual_end(struct nk_context *ctx)
22652 {
22653  struct nk_window *popup;
22654  struct nk_panel *panel;
22655  NK_ASSERT(ctx);
22656  NK_ASSERT(ctx->current);
22657  if (!ctx || !ctx->current) return;
22658 
22659  popup = ctx->current;
22660  panel = popup->layout;
22661  NK_ASSERT(popup->parent);
22662  NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
22663  if (panel->flags & NK_WINDOW_DYNAMIC) {
22664  /* Close behavior
22665  This is a bit of a hack solution since we do not know before we end our popup
22666  how big it will be. We therefore do not directly know when a
22667  click outside the non-blocking popup must close it at that direct frame.
22668  Instead it will be closed in the next frame.*/
22669  struct nk_rect body = {0,0,0,0};
22670  if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
22671  struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
22672  body = panel->bounds;
22673  body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
22674  body.h = (panel->bounds.y + panel->bounds.h) - body.y;
22675  }
22676  {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22677  int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22678  if (pressed && in_body)
22679  popup->flags |= NK_WINDOW_HIDDEN;
22680  }
22681  }
22682  if (popup->flags & NK_WINDOW_HIDDEN)
22683  popup->seq = 0;
22684  nk_popup_end(ctx);
22685  return;
22686 }
22687 /* -------------------------------------------------------------
22688  *
22689  * COMBO
22690  *
22691  * --------------------------------------------------------------*/
22692 NK_INTERN int
22693 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
22694  struct nk_vec2 size, int is_clicked, struct nk_rect header)
22695 {
22696  struct nk_window *popup;
22697  int is_open = 0;
22698  int is_active = 0;
22699  struct nk_rect body;
22700  nk_hash hash;
22701 
22702  NK_ASSERT(ctx);
22703  NK_ASSERT(ctx->current);
22704  NK_ASSERT(ctx->current->layout);
22705  if (!ctx || !ctx->current || !ctx->current->layout)
22706  return 0;
22707 
22708  popup = win->popup.win;
22709  body.x = header.x;
22710  body.w = size.x;
22711  body.y = header.y + header.h-ctx->style.window.combo_border;
22712  body.h = size.y;
22713 
22714  hash = win->popup.combo_count++;
22715  is_open = (popup) ? nk_true:nk_false;
22716  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
22717  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
22718  (!is_open && !is_active && !is_clicked)) return 0;
22719  if (!nk_nonblock_begin(ctx, 0, body,
22720  (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
22721 
22722  win->popup.type = NK_PANEL_COMBO;
22723  win->popup.name = hash;
22724  return 1;
22725 }
22726 
22727 NK_API int
22728 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
22729  struct nk_vec2 size)
22730 {
22731  const struct nk_input *in;
22732  struct nk_window *win;
22733  struct nk_style *style;
22734 
22735  enum nk_widget_layout_states s;
22736  int is_clicked = nk_false;
22737  struct nk_rect header;
22738  const struct nk_style_item *background;
22739  struct nk_text text;
22740 
22741  NK_ASSERT(ctx);
22742  NK_ASSERT(selected);
22743  NK_ASSERT(ctx->current);
22744  NK_ASSERT(ctx->current->layout);
22745  if (!ctx || !ctx->current || !ctx->current->layout || !selected)
22746  return 0;
22747 
22748  win = ctx->current;
22749  style = &ctx->style;
22750  s = nk_widget(&header, ctx);
22751  if (s == NK_WIDGET_INVALID)
22752  return 0;
22753 
22754  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22755  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22756  is_clicked = nk_true;
22757 
22758  /* draw combo box header background and border */
22759  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22760  background = &style->combo.active;
22761  text.text = style->combo.label_active;
22762  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22763  background = &style->combo.hover;
22764  text.text = style->combo.label_hover;
22765  } else {
22766  background = &style->combo.normal;
22767  text.text = style->combo.label_normal;
22768  }
22769  if (background->type == NK_STYLE_ITEM_IMAGE) {
22770  text.background = nk_rgba(0,0,0,0);
22771  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22772  } else {
22773  text.background = background->data.color;
22774  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22775  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22776  }
22777  {
22778  /* print currently selected text item */
22779  struct nk_rect label;
22780  struct nk_rect button;
22781  struct nk_rect content;
22782 
22783  enum nk_symbol_type sym;
22784  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22785  sym = style->combo.sym_hover;
22786  else if (is_clicked)
22787  sym = style->combo.sym_active;
22788  else sym = style->combo.sym_normal;
22789 
22790  /* calculate button */
22791  button.w = header.h - 2 * style->combo.button_padding.y;
22792  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22793  button.y = header.y + style->combo.button_padding.y;
22794  button.h = button.w;
22795 
22796  content.x = button.x + style->combo.button.padding.x;
22797  content.y = button.y + style->combo.button.padding.y;
22798  content.w = button.w - 2 * style->combo.button.padding.x;
22799  content.h = button.h - 2 * style->combo.button.padding.y;
22800 
22801  /* draw selected label */
22802  text.padding = nk_vec2(0,0);
22803  label.x = header.x + style->combo.content_padding.x;
22804  label.y = header.y + style->combo.content_padding.y;
22805  label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
22806  label.h = header.h - 2 * style->combo.content_padding.y;
22807  nk_widget_text(&win->buffer, label, selected, len, &text,
22808  NK_TEXT_LEFT, ctx->style.font);
22809 
22810  /* draw open/close button */
22811  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22812  &ctx->style.combo.button, sym, style->font);
22813  }
22814  return nk_combo_begin(ctx, win, size, is_clicked, header);
22815 }
22816 
22817 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
22818 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);}
22819 
22820 NK_API int
22821 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
22822 {
22823  struct nk_window *win;
22824  struct nk_style *style;
22825  const struct nk_input *in;
22826 
22827  struct nk_rect header;
22828  int is_clicked = nk_false;
22829  enum nk_widget_layout_states s;
22830  const struct nk_style_item *background;
22831 
22832  NK_ASSERT(ctx);
22833  NK_ASSERT(ctx->current);
22834  NK_ASSERT(ctx->current->layout);
22835  if (!ctx || !ctx->current || !ctx->current->layout)
22836  return 0;
22837 
22838  win = ctx->current;
22839  style = &ctx->style;
22840  s = nk_widget(&header, ctx);
22841  if (s == NK_WIDGET_INVALID)
22842  return 0;
22843 
22844  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22845  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22846  is_clicked = nk_true;
22847 
22848  /* draw combo box header background and border */
22849  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22850  background = &style->combo.active;
22851  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22852  background = &style->combo.hover;
22853  else background = &style->combo.normal;
22854 
22855  if (background->type == NK_STYLE_ITEM_IMAGE) {
22856  nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
22857  } else {
22858  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22859  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22860  }
22861  {
22862  struct nk_rect content;
22863  struct nk_rect button;
22864  struct nk_rect bounds;
22865 
22866  enum nk_symbol_type sym;
22867  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22868  sym = style->combo.sym_hover;
22869  else if (is_clicked)
22870  sym = style->combo.sym_active;
22871  else sym = style->combo.sym_normal;
22872 
22873  /* calculate button */
22874  button.w = header.h - 2 * style->combo.button_padding.y;
22875  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22876  button.y = header.y + style->combo.button_padding.y;
22877  button.h = button.w;
22878 
22879  content.x = button.x + style->combo.button.padding.x;
22880  content.y = button.y + style->combo.button.padding.y;
22881  content.w = button.w - 2 * style->combo.button.padding.x;
22882  content.h = button.h - 2 * style->combo.button.padding.y;
22883 
22884  /* draw color */
22885  bounds.h = header.h - 4 * style->combo.content_padding.y;
22886  bounds.y = header.y + 2 * style->combo.content_padding.y;
22887  bounds.x = header.x + 2 * style->combo.content_padding.x;
22888  bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
22889  nk_fill_rect(&win->buffer, bounds, 0, color);
22890 
22891  /* draw open/close button */
22892  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22893  &ctx->style.combo.button, sym, style->font);
22894  }
22895  return nk_combo_begin(ctx, win, size, is_clicked, header);
22896 }
22897 
22898 NK_API int
22899 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
22900 {
22901  struct nk_window *win;
22902  struct nk_style *style;
22903  const struct nk_input *in;
22904 
22905  struct nk_rect header;
22906  int is_clicked = nk_false;
22907  enum nk_widget_layout_states s;
22908  const struct nk_style_item *background;
22909  struct nk_color sym_background;
22910  struct nk_color symbol_color;
22911 
22912  NK_ASSERT(ctx);
22913  NK_ASSERT(ctx->current);
22914  NK_ASSERT(ctx->current->layout);
22915  if (!ctx || !ctx->current || !ctx->current->layout)
22916  return 0;
22917 
22918  win = ctx->current;
22919  style = &ctx->style;
22920  s = nk_widget(&header, ctx);
22921  if (s == NK_WIDGET_INVALID)
22922  return 0;
22923 
22924  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22925  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22926  is_clicked = nk_true;
22927 
22928  /* draw combo box header background and border */
22929  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22930  background = &style->combo.active;
22931  symbol_color = style->combo.symbol_active;
22932  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22933  background = &style->combo.hover;
22934  symbol_color = style->combo.symbol_hover;
22935  } else {
22936  background = &style->combo.normal;
22937  symbol_color = style->combo.symbol_hover;
22938  }
22939 
22940  if (background->type == NK_STYLE_ITEM_IMAGE) {
22941  sym_background = nk_rgba(0,0,0,0);
22942  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22943  } else {
22944  sym_background = background->data.color;
22945  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22946  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22947  }
22948  {
22949  struct nk_rect bounds = {0,0,0,0};
22950  struct nk_rect content;
22951  struct nk_rect button;
22952 
22953  enum nk_symbol_type sym;
22954  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22955  sym = style->combo.sym_hover;
22956  else if (is_clicked)
22957  sym = style->combo.sym_active;
22958  else sym = style->combo.sym_normal;
22959 
22960  /* calculate button */
22961  button.w = header.h - 2 * style->combo.button_padding.y;
22962  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
22963  button.y = header.y + style->combo.button_padding.y;
22964  button.h = button.w;
22965 
22966  content.x = button.x + style->combo.button.padding.x;
22967  content.y = button.y + style->combo.button.padding.y;
22968  content.w = button.w - 2 * style->combo.button.padding.x;
22969  content.h = button.h - 2 * style->combo.button.padding.y;
22970 
22971  /* draw symbol */
22972  bounds.h = header.h - 2 * style->combo.content_padding.y;
22973  bounds.y = header.y + style->combo.content_padding.y;
22974  bounds.x = header.x + style->combo.content_padding.x;
22975  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
22976  nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
22977  1.0f, style->font);
22978 
22979  /* draw open/close button */
22980  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
22981  &ctx->style.combo.button, sym, style->font);
22982  }
22983  return nk_combo_begin(ctx, win, size, is_clicked, header);
22984 }
22985 
22986 NK_API int
22987 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
22988  enum nk_symbol_type symbol, struct nk_vec2 size)
22989 {
22990  struct nk_window *win;
22991  struct nk_style *style;
22992  struct nk_input *in;
22993 
22994  struct nk_rect header;
22995  int is_clicked = nk_false;
22996  enum nk_widget_layout_states s;
22997  const struct nk_style_item *background;
22998  struct nk_color symbol_color;
22999  struct nk_text text;
23000 
23001  NK_ASSERT(ctx);
23002  NK_ASSERT(ctx->current);
23003  NK_ASSERT(ctx->current->layout);
23004  if (!ctx || !ctx->current || !ctx->current->layout)
23005  return 0;
23006 
23007  win = ctx->current;
23008  style = &ctx->style;
23009  s = nk_widget(&header, ctx);
23010  if (!s) return 0;
23011 
23012  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23013  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23014  is_clicked = nk_true;
23015 
23016  /* draw combo box header background and border */
23017  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23018  background = &style->combo.active;
23019  symbol_color = style->combo.symbol_active;
23020  text.text = style->combo.label_active;
23021  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23022  background = &style->combo.hover;
23023  symbol_color = style->combo.symbol_hover;
23024  text.text = style->combo.label_hover;
23025  } else {
23026  background = &style->combo.normal;
23027  symbol_color = style->combo.symbol_normal;
23028  text.text = style->combo.label_normal;
23029  }
23030  if (background->type == NK_STYLE_ITEM_IMAGE) {
23031  text.background = nk_rgba(0,0,0,0);
23032  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23033  } else {
23034  text.background = background->data.color;
23035  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23036  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23037  }
23038  {
23039  struct nk_rect content;
23040  struct nk_rect button;
23041  struct nk_rect label;
23042  struct nk_rect image;
23043 
23044  enum nk_symbol_type sym;
23045  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23046  sym = style->combo.sym_hover;
23047  else if (is_clicked)
23048  sym = style->combo.sym_active;
23049  else sym = style->combo.sym_normal;
23050 
23051  /* calculate button */
23052  button.w = header.h - 2 * style->combo.button_padding.y;
23053  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
23054  button.y = header.y + style->combo.button_padding.y;
23055  button.h = button.w;
23056 
23057  content.x = button.x + style->combo.button.padding.x;
23058  content.y = button.y + style->combo.button.padding.y;
23059  content.w = button.w - 2 * style->combo.button.padding.x;
23060  content.h = button.h - 2 * style->combo.button.padding.y;
23061  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
23062  &ctx->style.combo.button, sym, style->font);
23063 
23064  /* draw symbol */
23065  image.x = header.x + style->combo.content_padding.x;
23066  image.y = header.y + style->combo.content_padding.y;
23067  image.h = header.h - 2 * style->combo.content_padding.y;
23068  image.w = image.h;
23069  nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
23070  1.0f, style->font);
23071 
23072  /* draw label */
23073  text.padding = nk_vec2(0,0);
23074  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
23075  label.y = header.y + style->combo.content_padding.y;
23076  label.w = (button.x - style->combo.content_padding.x) - label.x;
23077  label.h = header.h - 2 * style->combo.content_padding.y;
23078  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
23079  }
23080  return nk_combo_begin(ctx, win, size, is_clicked, header);
23081 }
23082 
23083 NK_API int
23084 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
23085 {
23086  struct nk_window *win;
23087  struct nk_style *style;
23088  const struct nk_input *in;
23089 
23090  struct nk_rect header;
23091  int is_clicked = nk_false;
23092  enum nk_widget_layout_states s;
23093  const struct nk_style_item *background;
23094 
23095  NK_ASSERT(ctx);
23096  NK_ASSERT(ctx->current);
23097  NK_ASSERT(ctx->current->layout);
23098  if (!ctx || !ctx->current || !ctx->current->layout)
23099  return 0;
23100 
23101  win = ctx->current;
23102  style = &ctx->style;
23103  s = nk_widget(&header, ctx);
23104  if (s == NK_WIDGET_INVALID)
23105  return 0;
23106 
23107  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23108  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23109  is_clicked = nk_true;
23110 
23111  /* draw combo box header background and border */
23112  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
23113  background = &style->combo.active;
23114  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23115  background = &style->combo.hover;
23116  else background = &style->combo.normal;
23117 
23118  if (background->type == NK_STYLE_ITEM_IMAGE) {
23119  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23120  } else {
23121  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23122  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23123  }
23124  {
23125  struct nk_rect bounds = {0,0,0,0};
23126  struct nk_rect content;
23127  struct nk_rect button;
23128 
23129  enum nk_symbol_type sym;
23130  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23131  sym = style->combo.sym_hover;
23132  else if (is_clicked)
23133  sym = style->combo.sym_active;
23134  else sym = style->combo.sym_normal;
23135 
23136  /* calculate button */
23137  button.w = header.h - 2 * style->combo.button_padding.y;
23138  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
23139  button.y = header.y + style->combo.button_padding.y;
23140  button.h = button.w;
23141 
23142  content.x = button.x + style->combo.button.padding.x;
23143  content.y = button.y + style->combo.button.padding.y;
23144  content.w = button.w - 2 * style->combo.button.padding.x;
23145  content.h = button.h - 2 * style->combo.button.padding.y;
23146 
23147  /* draw image */
23148  bounds.h = header.h - 2 * style->combo.content_padding.y;
23149  bounds.y = header.y + style->combo.content_padding.y;
23150  bounds.x = header.x + style->combo.content_padding.x;
23151  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
23152  nk_draw_image(&win->buffer, bounds, &img, nk_white);
23153 
23154  /* draw open/close button */
23155  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
23156  &ctx->style.combo.button, sym, style->font);
23157  }
23158  return nk_combo_begin(ctx, win, size, is_clicked, header);
23159 }
23160 
23161 NK_API int
23162 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
23163  struct nk_image img, struct nk_vec2 size)
23164 {
23165  struct nk_window *win;
23166  struct nk_style *style;
23167  struct nk_input *in;
23168 
23169  struct nk_rect header;
23170  int is_clicked = nk_false;
23171  enum nk_widget_layout_states s;
23172  const struct nk_style_item *background;
23173  struct nk_text text;
23174 
23175  NK_ASSERT(ctx);
23176  NK_ASSERT(ctx->current);
23177  NK_ASSERT(ctx->current->layout);
23178  if (!ctx || !ctx->current || !ctx->current->layout)
23179  return 0;
23180 
23181  win = ctx->current;
23182  style = &ctx->style;
23183  s = nk_widget(&header, ctx);
23184  if (!s) return 0;
23185 
23186  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23187  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23188  is_clicked = nk_true;
23189 
23190  /* draw combo box header background and border */
23191  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23192  background = &style->combo.active;
23193  text.text = style->combo.label_active;
23194  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23195  background = &style->combo.hover;
23196  text.text = style->combo.label_hover;
23197  } else {
23198  background = &style->combo.normal;
23199  text.text = style->combo.label_normal;
23200  }
23201  if (background->type == NK_STYLE_ITEM_IMAGE) {
23202  text.background = nk_rgba(0,0,0,0);
23203  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23204  } else {
23205  text.background = background->data.color;
23206  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23207  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23208  }
23209  {
23210  struct nk_rect content;
23211  struct nk_rect button;
23212  struct nk_rect label;
23213  struct nk_rect image;
23214 
23215  enum nk_symbol_type sym;
23216  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23217  sym = style->combo.sym_hover;
23218  else if (is_clicked)
23219  sym = style->combo.sym_active;
23220  else sym = style->combo.sym_normal;
23221 
23222  /* calculate button */
23223  button.w = header.h - 2 * style->combo.button_padding.y;
23224  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
23225  button.y = header.y + style->combo.button_padding.y;
23226  button.h = button.w;
23227 
23228  content.x = button.x + style->combo.button.padding.x;
23229  content.y = button.y + style->combo.button.padding.y;
23230  content.w = button.w - 2 * style->combo.button.padding.x;
23231  content.h = button.h - 2 * style->combo.button.padding.y;
23232  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
23233  &ctx->style.combo.button, sym, style->font);
23234 
23235  /* draw image */
23236  image.x = header.x + style->combo.content_padding.x;
23237  image.y = header.y + style->combo.content_padding.y;
23238  image.h = header.h - 2 * style->combo.content_padding.y;
23239  image.w = image.h;
23240  nk_draw_image(&win->buffer, image, &img, nk_white);
23241 
23242  /* draw label */
23243  text.padding = nk_vec2(0,0);
23244  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
23245  label.y = header.y + style->combo.content_padding.y;
23246  label.w = (button.x - style->combo.content_padding.x) - label.x;
23247  label.h = header.h - 2 * style->combo.content_padding.y;
23248  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
23249  }
23250  return nk_combo_begin(ctx, win, size, is_clicked, header);
23251 }
23252 
23254  const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
23255 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);}
23256 
23258  const char *selected, struct nk_image img, struct nk_vec2 size)
23259 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);}
23260 
23261 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
23262 {return nk_contextual_item_text(ctx, text, len, align);}
23263 
23264 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23265 {return nk_contextual_item_label(ctx, label, align);}
23266 
23267 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
23268  int len, nk_flags alignment)
23269 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);}
23270 
23271 NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img,
23272  const char *text, nk_flags alignment)
23273 {return nk_contextual_item_image_label(ctx, img, text, alignment);}
23274 
23275 NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23276  const char *text, int len, nk_flags alignment)
23277 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);}
23278 
23280  const char *label, nk_flags alignment)
23281 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);}
23282 
23283 NK_API void nk_combo_end(struct nk_context *ctx)
23284 {nk_contextual_end(ctx);}
23285 
23286 NK_API void nk_combo_close(struct nk_context *ctx)
23287 {nk_contextual_close(ctx);}
23288 
23289 NK_API int
23290 nk_combo(struct nk_context *ctx, const char **items, int count,
23291  int selected, int item_height, struct nk_vec2 size)
23292 {
23293  int i = 0;
23294  int max_height;
23295  struct nk_vec2 item_spacing;
23296  struct nk_vec2 window_padding;
23297 
23298  NK_ASSERT(ctx);
23299  NK_ASSERT(items);
23300  NK_ASSERT(ctx->current);
23301  if (!ctx || !items ||!count)
23302  return selected;
23303 
23304  item_spacing = ctx->style.window.spacing;
23305  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23306  max_height = count * item_height + count * (int)item_spacing.y;
23307  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23308  size.y = NK_MIN(size.y, (float)max_height);
23309  if (nk_combo_begin_label(ctx, items[selected], size)) {
23310  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23311  for (i = 0; i < count; ++i) {
23312  if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
23313  selected = i;
23314  }
23315  nk_combo_end(ctx);
23316  }
23317  return selected;
23318 }
23319 
23320 NK_API int
23321 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23322  int separator, int selected, int count, int item_height, struct nk_vec2 size)
23323 {
23324  int i;
23325  int max_height;
23326  struct nk_vec2 item_spacing;
23327  struct nk_vec2 window_padding;
23328  const char *current_item;
23329  const char *iter;
23330  int length = 0;
23331 
23332  NK_ASSERT(ctx);
23333  NK_ASSERT(items_separated_by_separator);
23334  if (!ctx || !items_separated_by_separator)
23335  return selected;
23336 
23337  /* calculate popup window */
23338  item_spacing = ctx->style.window.spacing;
23339  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23340  max_height = count * item_height + count * (int)item_spacing.y;
23341  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23342  size.y = NK_MIN(size.y, (float)max_height);
23343 
23344  /* find selected item */
23345  current_item = items_separated_by_separator;
23346  for (i = 0; i < count; ++i) {
23347  iter = current_item;
23348  while (*iter && *iter != separator) iter++;
23349  length = (int)(iter - current_item);
23350  if (i == selected) break;
23351  current_item = iter + 1;
23352  }
23353 
23354  if (nk_combo_begin_text(ctx, current_item, length, size)) {
23355  current_item = items_separated_by_separator;
23356  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23357  for (i = 0; i < count; ++i) {
23358  iter = current_item;
23359  while (*iter && *iter != separator) iter++;
23360  length = (int)(iter - current_item);
23361  if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
23362  selected = i;
23363  current_item = current_item + length + 1;
23364  }
23365  nk_combo_end(ctx);
23366  }
23367  return selected;
23368 }
23369 
23370 NK_API int
23371 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23372  int selected, int count, int item_height, struct nk_vec2 size)
23373 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);}
23374 
23375 NK_API int
23376 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
23377  void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
23378 {
23379  int i;
23380  int max_height;
23381  struct nk_vec2 item_spacing;
23382  struct nk_vec2 window_padding;
23383  const char *item;
23384 
23385  NK_ASSERT(ctx);
23386  NK_ASSERT(item_getter);
23387  if (!ctx || !item_getter)
23388  return selected;
23389 
23390  /* calculate popup window */
23391  item_spacing = ctx->style.window.spacing;
23392  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23393  max_height = count * item_height + count * (int)item_spacing.y;
23394  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23395  size.y = NK_MIN(size.y, (float)max_height);
23396 
23397  item_getter(userdata, selected, &item);
23398  if (nk_combo_begin_label(ctx, item, size)) {
23399  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23400  for (i = 0; i < count; ++i) {
23401  item_getter(userdata, i, &item);
23402  if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
23403  selected = i;
23404  }
23405  nk_combo_end(ctx);
23406  }
23407  return selected;
23408 }
23409 
23410 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count,
23411  int *selected, int item_height, struct nk_vec2 size)
23412 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);}
23413 
23414 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23415  int *selected, int count, int item_height, struct nk_vec2 size)
23416 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);}
23417 
23418 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23419  int separator,int *selected, int count, int item_height, struct nk_vec2 size)
23420 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
23421  *selected, count, item_height, size);}
23422 
23423 NK_API void nk_combobox_callback(struct nk_context *ctx,
23424  void(*item_getter)(void* data, int id, const char **out_text),
23425  void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
23426 {*selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);}
23427 
23428 /*
23429  * -------------------------------------------------------------
23430  *
23431  * MENU
23432  *
23433  * --------------------------------------------------------------
23434  */
23435 NK_INTERN int
23436 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
23437  const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
23438 {
23439  int is_open = 0;
23440  int is_active = 0;
23441  struct nk_rect body;
23442  struct nk_window *popup;
23443  nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
23444 
23445  NK_ASSERT(ctx);
23446  NK_ASSERT(ctx->current);
23447  NK_ASSERT(ctx->current->layout);
23448  if (!ctx || !ctx->current || !ctx->current->layout)
23449  return 0;
23450 
23451  body.x = header.x;
23452  body.w = size.x;
23453  body.y = header.y + header.h;
23454  body.h = size.y;
23455 
23456  popup = win->popup.win;
23457  is_open = popup ? nk_true : nk_false;
23458  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
23459  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
23460  (!is_open && !is_active && !is_clicked)) return 0;
23461  if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
23462  return 0;
23463 
23464  win->popup.type = NK_PANEL_MENU;
23465  win->popup.name = hash;
23466  return 1;
23467 }
23468 
23469 NK_API int
23470 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
23471  nk_flags align, struct nk_vec2 size)
23472 {
23473  struct nk_window *win;
23474  const struct nk_input *in;
23475  struct nk_rect header;
23476  int is_clicked = nk_false;
23477  nk_flags state;
23478 
23479  NK_ASSERT(ctx);
23480  NK_ASSERT(ctx->current);
23481  NK_ASSERT(ctx->current->layout);
23482  if (!ctx || !ctx->current || !ctx->current->layout)
23483  return 0;
23484 
23485  win = ctx->current;
23486  state = nk_widget(&header, ctx);
23487  if (!state) return 0;
23488  in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23489  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
23490  title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23491  is_clicked = nk_true;
23492  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23493 }
23494 
23495 NK_API int nk_menu_begin_label(struct nk_context *ctx,
23496  const char *text, nk_flags align, struct nk_vec2 size)
23497 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);}
23498 
23499 NK_API int
23500 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
23501  struct nk_vec2 size)
23502 {
23503  struct nk_window *win;
23504  struct nk_rect header;
23505  const struct nk_input *in;
23506  int is_clicked = nk_false;
23507  nk_flags state;
23508 
23509  NK_ASSERT(ctx);
23510  NK_ASSERT(ctx->current);
23511  NK_ASSERT(ctx->current->layout);
23512  if (!ctx || !ctx->current || !ctx->current->layout)
23513  return 0;
23514 
23515  win = ctx->current;
23516  state = nk_widget(&header, ctx);
23517  if (!state) return 0;
23518  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23519  if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
23520  img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
23521  is_clicked = nk_true;
23522  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23523 }
23524 
23525 NK_API int
23526 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
23527  enum nk_symbol_type sym, struct nk_vec2 size)
23528 {
23529  struct nk_window *win;
23530  const struct nk_input *in;
23531  struct nk_rect header;
23532  int is_clicked = nk_false;
23533  nk_flags state;
23534 
23535  NK_ASSERT(ctx);
23536  NK_ASSERT(ctx->current);
23537  NK_ASSERT(ctx->current->layout);
23538  if (!ctx || !ctx->current || !ctx->current->layout)
23539  return 0;
23540 
23541  win = ctx->current;
23542  state = nk_widget(&header, ctx);
23543  if (!state) return 0;
23544  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23545  if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
23546  sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23547  is_clicked = nk_true;
23548  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23549 }
23550 
23551 NK_API int
23552 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
23553  nk_flags align, struct nk_image img, struct nk_vec2 size)
23554 {
23555  struct nk_window *win;
23556  struct nk_rect header;
23557  const struct nk_input *in;
23558  int is_clicked = nk_false;
23559  nk_flags state;
23560 
23561  NK_ASSERT(ctx);
23562  NK_ASSERT(ctx->current);
23563  NK_ASSERT(ctx->current->layout);
23564  if (!ctx || !ctx->current || !ctx->current->layout)
23565  return 0;
23566 
23567  win = ctx->current;
23568  state = nk_widget(&header, ctx);
23569  if (!state) return 0;
23570  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23571  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
23572  header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23573  ctx->style.font, in))
23574  is_clicked = nk_true;
23575  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23576 }
23577 
23579  const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
23580 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);}
23581 
23582 NK_API int
23583 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
23584  nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
23585 {
23586  struct nk_window *win;
23587  struct nk_rect header;
23588  const struct nk_input *in;
23589  int is_clicked = nk_false;
23590  nk_flags state;
23591 
23592  NK_ASSERT(ctx);
23593  NK_ASSERT(ctx->current);
23594  NK_ASSERT(ctx->current->layout);
23595  if (!ctx || !ctx->current || !ctx->current->layout)
23596  return 0;
23597 
23598  win = ctx->current;
23599  state = nk_widget(&header, ctx);
23600  if (!state) return 0;
23601 
23602  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23603  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
23604  header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23605  ctx->style.font, in)) is_clicked = nk_true;
23606  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23607 }
23608 
23610  const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
23611 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);}
23612 
23613 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
23614 {return nk_contextual_item_text(ctx, title, len, align);}
23615 
23616 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23617 {return nk_contextual_item_label(ctx, label, align);}
23618 
23619 NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img,
23620  const char *label, nk_flags align)
23621 {return nk_contextual_item_image_label(ctx, img, label, align);}
23622 
23623 NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img,
23624  const char *text, int len, nk_flags align)
23625 {return nk_contextual_item_image_text(ctx, img, text, len, align);}
23626 
23627 NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym,
23628  const char *text, int len, nk_flags align)
23629 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);}
23630 
23631 NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym,
23632  const char *label, nk_flags align)
23633 {return nk_contextual_item_symbol_label(ctx, sym, label, align);}
23634 
23635 NK_API void nk_menu_close(struct nk_context *ctx)
23636 {nk_contextual_close(ctx);}
23637 
23638 NK_API void
23639 nk_menu_end(struct nk_context *ctx)
23640 {nk_contextual_end(ctx);}
23641 
23642 #endif
Definition: nuklear.h:2021
unsigned short r
Definition: nuklear.h:3063
struct nk_vec2 padding
Definition: nuklear.h:3630
Definition: nuklear.h:3126
Definition: nuklear.h:2146
NK_API struct nk_color nk_rgb_iv(const int *rgb)
struct nk_command header
Definition: nuklear.h:2976
Definition: nuklear.h:689
short cx
Definition: nuklear.h:3062
NK_API int nk_menu_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_style_item hover
Definition: nuklear.h:3580
nk_chart_event
Definition: nuklear.h:472
struct nk_vec2 padding
Definition: nuklear.h:3536
float preferred_x
Definition: nuklear.h:2860
struct nk_style_item hover_active
Definition: nuklear.h:3452
NK_API int nk_window_has_focus(const struct nk_context *)
NK_API int nk_menu_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
Definition: nuklear.h:3850
struct nk_style_button dec_button
Definition: nuklear.h:3634
NK_API struct nk_rect nk_rectv(const float *xywh)
nk_handle userdata
Definition: nuklear.h:3539
Definition: nuklear.h:2009
#define NK_CONFIG_STACK(type, size)
Definition: nuklear.h:4054
struct nk_style_item cursor_hover
Definition: nuklear.h:3423
struct nk_command header
Definition: nuklear.h:3029
NK_API int nk_input_mouse_clicked(const struct nk_input *, enum nk_buttons, struct nk_rect)
struct nk_pool pool
Definition: nuklear.h:4161
struct nk_style_item active
Definition: nuklear.h:3483
NK_API int nk_select_text(struct nk_context *, const char *, int, nk_flags align, int value)
NK_API int nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
unsigned int scrolled
Definition: nuklear.h:3985
NK_API void nk_window_set_position(struct nk_context *, struct nk_vec2 pos)
NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba)
float menu_border
Definition: nuklear.h:3754
NK_API int nk_contextual_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
NK_API void nk_textedit_select_all(struct nk_text_edit *)
struct nk_style_button close_button
Definition: nuklear.h:3719
Definition: nuklear.h:3060
nk_convert_result
Definition: nuklear.h:970
NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align)
NK_API int nk_contextual_begin(struct nk_context *, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds)
struct nk_vec2 last
Definition: nuklear.h:3835
struct nk_color label_normal
Definition: nuklear.h:3726
struct nk_color text_hover
Definition: nuklear.h:3457
Definition: nuklear.h:3829
Definition: nuklear.h:3051
int show_buttons
Definition: nuklear.h:3565
void * memory
Definition: nuklear.h:2657
struct nk_style_item cursor_normal
Definition: nuklear.h:3422
Definition: nuklear.h:3163
NK_API void nk_color_hex_rgb(char *output, struct nk_color)
float rounding_cursor
Definition: nuklear.h:3561
Definition: nuklear.h:2160
float border
Definition: nuklear.h:3402
float border
Definition: nuklear.h:3895
NK_API struct nk_rect nk_get_null_rect(void)
nk_buffer_allocation_type
Definition: nuklear.h:2670
NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
void *(* nk_plugin_alloc)(nk_handle, void *old, nk_size)
Definition: nuklear.h:478
struct nk_color color
Definition: nuklear.h:3065
#define NK_STORAGE
Definition: nuklear.h:287
nk_handle userdata
Definition: nuklear.h:3513
nk_widget_states
Definition: nuklear.h:1835
void(* nk_plugin_paste)(nk_handle, struct nk_text_edit *)
Definition: nuklear.h:481
Definition: nuklear.h:1184
float tooltip_border
Definition: nuklear.h:3756
float max_x
Definition: nuklear.h:3892
#define NK_INT32
Definition: nuklear.h:352
NK_API int nk_contextual_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
unsigned int page_count
Definition: nuklear.h:4122
nk_size allocated
Definition: nuklear.h:2693
unsigned short w
Definition: nuklear.h:3012
NK_API void nk_stroke_circle(struct nk_command_buffer *, struct nk_rect, float line_thickness, struct nk_color)
NK_API struct nk_vec2 nk_vec2i(int x, int y)
Definition: nuklear.h:1183
struct nk_vec2 contextual_padding
Definition: nuklear.h:3769
Definition: nuklear.h:2161
nk_panel_flags
Definition: nuklear.h:1173
NK_API int nk_utf_decode(const char *, nk_rune *, int)
struct nk_style_button menu_button
Definition: nuklear.h:3784
Definition: nuklear.h:2015
NK_API struct nk_color nk_rgba_u32(nk_uint)
nk_size needed
Definition: nuklear.h:2695
NK_API int nk_filter_hex(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_menu_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
float bar_height
Definition: nuklear.h:3500
unsigned short w
Definition: nuklear.h:3005
NK_API void nk_buffer_init(struct nk_buffer *, const struct nk_allocator *, nk_size size)
NK_API int nk_button_color(struct nk_context *, struct nk_color)
unsigned short h
Definition: nuklear.h:3047
NK_API int nk_select_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int value)
NK_API struct nk_window * nk_window_find(struct nk_context *ctx, const char *name)
NK_API void nk_str_remove_chars(struct nk_str *, int len)
NK_API int nk_widget_is_hovered(struct nk_context *)
#define NK_FLAGS_STACK_SIZE
Definition: nuklear.h:4042
NK_API void nk_layout_row_end(struct nk_context *)
Definition: nuklear.h:2939
Definition: nuklear.h:664
NK_API void nk_fill_circle(struct nk_command_buffer *, struct nk_rect, struct nk_color)
NK_API void nk_window_set_size(struct nk_context *, struct nk_vec2)
struct nk_vec2 padding
Definition: nuklear.h:3384
#define nk_zero_struct(s)
Definition: nuklear.h:4197
struct nk_color label_active
Definition: nuklear.h:3728
struct nk_image img
Definition: nuklear.h:462
Definition: nuklear.h:3925
Definition: deflate.c:117
struct nk_color text_normal
Definition: nuklear.h:3396
Definition: nuklear.h:2672
nk_handle handle
Definition: nuklear.h:461
float border
Definition: nuklear.h:3628
Definition: nuklear.h:453
unsigned int seq
Definition: nuklear.h:3945
Definition: nuklear.h:3189
float rounding
Definition: nuklear.h:3559
Definition: nuklear.h:3821
short x
Definition: nuklear.h:2971
enum nk_symbol_type sym_left
Definition: nuklear.h:3624
struct nk_config_stack_button_behavior button_behaviors
Definition: nuklear.h:4084
nk_flags text_alignment
Definition: nuklear.h:3399
struct nk_rect clip
Definition: nuklear.h:3897
short y
Definition: nuklear.h:3011
struct config_s config
Definition: nuklear.h:670
nk_modify
Definition: nuklear.h:467
Definition: nuklear.h:484
struct nk_color selected_text_hover
Definition: nuklear.h:3600
NK_API int nk_combo_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down)
float y
Definition: nuklear.h:3882
short h
Definition: nuklear.h:458
NK_API void nk_str_init_fixed(struct nk_str *, void *memory, nk_size size)
Definition: nuklear.h:3943
struct nk_color col
Definition: nuklear.h:3096
NK_API int nk_popup_begin(struct nk_context *, enum nk_popup_type, const char *, nk_flags, struct nk_rect bounds)
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
nk_style_header_align
Definition: nuklear.h:3708
struct nk_vec2 touch_padding
Definition: nuklear.h:3434
Definition: nuklear.h:2007
NK_API int nk_button_text_styled(struct nk_context *, const struct nk_style_button *, const char *title, int len)
struct nk_row_layout row
Definition: nuklear.h:3899
unsigned short line_thickness
Definition: nuklear.h:3086
unsigned int seq
Definition: nuklear.h:4094
struct nk_style_button node_maximize_button
Definition: nuklear.h:3695
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect)
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
int cursor
Definition: nuklear.h:3960
NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color)
struct nk_vec2 tooltip_padding
Definition: nuklear.h:3771
Definition: nuklear.h:465
NK_API void nk_combobox_callback(struct nk_context *, void(*item_getter)(void *, int, const char **), void *, int *selected, int count, int item_height, struct nk_vec2 size)
NK_API int nk_combo_item_text(struct nk_context *, const char *, int, nk_flags alignment)
Definition: nuklear.h:683
NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context *, nk_flags, char *buffer, int max, nk_plugin_filter)
struct nk_window * current
Definition: nuklear.h:4165
NK_API void nk_text(struct nk_context *, const char *, int, nk_flags)
nk_flags flags
Definition: nuklear.h:3973
Definition: nuklear.h:2952
Definition: nuklear.h:3817
struct nk_color color
Definition: nuklear.h:3033
Definition: nuklear.h:3826
Definition: nuklear.h:4119
nk_uint values[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:4097
Definition: nuklear.h:1998
float border
Definition: nuklear.h:3650
NK_API int nk_select_label(struct nk_context *, const char *, nk_flags align, int value)
float h
Definition: nuklear.h:3841
NK_API int nk_menu_item_label(struct nk_context *, const char *, nk_flags alignment)
struct nk_color color
Definition: nuklear.h:2980
Definition: nuklear.h:3854
float cursor_size
Definition: nuklear.h:3605
NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context *)
struct nk_vec2i c
Definition: nuklear.h:3024
struct nk_color selected_text_normal
Definition: nuklear.h:3599
Definition: nuklear.h:3642
float w
Definition: nuklear.h:3841
Definition: nuklear.h:1871
NK_API int nk_button_symbol_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type)
float item_height
Definition: nuklear.h:3865
struct nk_color color
Definition: nuklear.h:2989
struct nk_chart_slot slots[NK_CHART_MAX_SLOT]
Definition: nuklear.h:3842
float border
Definition: nuklear.h:3436
struct nk_color text_normal_active
Definition: nuklear.h:3461
char nk_glyph[NK_UTF_SIZE]
Definition: nuklear.h:459
nk_plugin_free free
Definition: nuklear.h:487
NK_POINTER_TYPE nk_ptr
Definition: nuklear.h:402
NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context *, struct nk_rect)
Definition: nuklear.h:492
nk_handle texture
Definition: nuklear.h:978
Definition: nuklear.h:1799
NK_API struct nk_color nk_hsv(int h, int s, int v)
struct nk_chart chart
Definition: nuklear.h:3900
struct nk_color tooltip_border_color
Definition: nuklear.h:3748
struct nk_vec2 image_padding
Definition: nuklear.h:3471
int where
Definition: nuklear.h:2818
nk_flags text_alignment
Definition: nuklear.h:3465
struct nk_vec2 cursor_size
Definition: nuklear.h:3503
struct nk_color group_border_color
Definition: nuklear.h:3747
struct nk_style_item scaler
Definition: nuklear.h:3749
Definition: nuklear.h:1174
#define NK_ABS(a)
Definition: nuklear.h:4181
nk_buttons
Definition: nuklear.h:695
NK_API void nk_edit_focus(struct nk_context *, nk_flags flags)
Definition: nuklear.h:3873
unsigned short point_count
Definition: nuklear.h:3072
Definition: nuklear.h:476
#define NK_MAX_FLOAT_PRECISION
Definition: nuklear.h:4176
#define NK_MAX_NUMBER_BUFFER
Definition: nuklear.h:260
unsigned char ungrab
Definition: nuklear.h:3176
short insert_length
Definition: nuklear.h:2819
short x
Definition: nuklear.h:3038
Definition: nuklear.h:3846
nk_edit_types
Definition: nuklear.h:2011
NK_API struct nk_color nk_hsv_fv(const float *hsv)
NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
Definition: nuklear.h:2014
nk_anti_aliasing
Definition: nuklear.h:969
NK_API int nk_widget_is_mouse_clicked(struct nk_context *, enum nk_buttons)
struct nk_color bar_hover
Definition: nuklear.h:3488
struct nk_style_progress progress
Definition: nuklear.h:3789
NK_API void nk_window_collapse(struct nk_context *, const char *name, enum nk_collapse_states state)
Definition: nuklear.h:3815
short y
Definition: nuklear.h:458
Definition: nuklear.h:2174
NK_API void nk_button_set_behavior(struct nk_context *, enum nk_button_behavior)
nk_handle userdata
Definition: nuklear.h:2812
NK_API void nk_group_end(struct nk_context *)
NK_API int nk_input_is_key_pressed(const struct nk_input *, enum nk_keys)
unsigned short point_count
Definition: nuklear.h:3079
struct nk_style_item normal
Definition: nuklear.h:3446
#define NK_FLAG(x)
Definition: nuklear.h:290
unsigned short w
Definition: nuklear.h:2997
int32_t current
Definition: netobject.cpp:37
unsigned short line_thickness
Definition: nuklear.h:2977
#define NK_UTF_INVALID
Definition: nuklear.h:4175
unsigned short h
Definition: nuklear.h:3094
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3574
struct nk_color top
Definition: nuklear.h:3014
Definition: nuklear.h:3816
struct nk_property_state property
Definition: nuklear.h:3982
NK_API void nk_layout_space_end(struct nk_context *)
#define NK_GLOBAL
Definition: nuklear.h:288
struct nk_style_item active
Definition: nuklear.h:3581
struct nk_style_item cursor_hover
Definition: nuklear.h:3494
nk_flags flags
Definition: nuklear.h:3888
struct nk_color border_color
Definition: nuklear.h:3742
struct nk_color text_pressed
Definition: nuklear.h:3458
Definition: nuklear.h:2022
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
short y
Definition: nuklear.h:2996
float min
Definition: nuklear.h:3833
unsigned short w
Definition: nuklear.h:3094
struct nk_style_item normal
Definition: nuklear.h:3389
struct nk_page_element * freelist
Definition: nuklear.h:4166
Definition: nuklear.h:2844
Definition: nuklear.h:3009
struct nk_vec2i c
Definition: nuklear.h:3032
struct nk_style_selectable selectable
Definition: nuklear.h:3787
NK_API int nk_str_insert_str_runes(struct nk_str *, int pos, const nk_rune *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3638
enum nk_symbol_type sym_minimize
Definition: nuklear.h:3697
struct nk_style_button inc_button
Definition: nuklear.h:3507
nk_handle userdata
Definition: nuklear.h:3439
#define NK_ALIGNOF(t)
Definition: nuklear.h:4240
Definition: nuklear.h:969
struct nk_style_window window
Definition: nuklear.h:3797
float height
Definition: nuklear.h:3860
unsigned char grab
Definition: nuklear.h:3174
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3569
int select_start
Definition: nuklear.h:2851
struct nk_vec2i ctrl[2]
Definition: nuklear.h:2988
float group_border
Definition: nuklear.h:3755
NK_API void nk_stroke_triangle(struct nk_command_buffer *, float, float, float, float, float, float, float line_thichness, struct nk_color)
NK_SIZE_TYPE nk_size
Definition: nuklear.h:401
unsigned short w
Definition: nuklear.h:2972
Definition: nuklear.h:3914
unsigned short line_thickness
Definition: nuklear.h:3021
struct nk_color border_color
Definition: nuklear.h:3582
struct nk_color text_normal
Definition: nuklear.h:3456
nk_panel_row_layout_type
Definition: nuklear.h:3845
struct nk_style_button contextual_button
Definition: nuklear.h:3783
Definition: nuklear.h:3179
NK_API void nk_label_wrap(struct nk_context *, const char *)
NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv)
Definition: nuklear.h:465
struct nk_style_item hover
Definition: nuklear.h:3390
NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score)
NK_API void nk_window_set_focus(struct nk_context *, const char *name)
Definition: nuklear.h:1175
Definition: nuklear.h:2150
NK_API void nk_str_delete_runes(struct nk_str *, int pos, int len)
struct nk_vec2 padding
Definition: nuklear.h:3562
#define NK_POINTER_TYPE
Definition: nuklear.h:389
Definition: nuklear.h:663
::std::string string
Definition: gtest-port.h:872
unsigned int seq
Definition: nuklear.h:3964
NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva)
#define SEEK_END
Definition: zconf.h:390
NK_API int nk_utf_encode(nk_rune, char *, int)
NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color)
nk_byte r
Definition: nuklear.h:453
float a[2]
Definition: nuklear.h:3056
Definition: nuklear.h:2839
NK_API int nk_str_append_text_char(struct nk_str *, const char *, int)
struct nk_color border_color
Definition: nuklear.h:3660
float rounding
Definition: nuklear.h:3403
NK_API void nk_fill_rect_multi_color(struct nk_command_buffer *, struct nk_rect, struct nk_color left, struct nk_color top, struct nk_color right, struct nk_color bottom)
struct nk_memory memory
Definition: nuklear.h:2689
NK_API void nk_list_view_end(struct nk_list_view *)
struct nk_color color
Definition: nuklear.h:3085
float header_height
Definition: nuklear.h:3894
unsigned con_old
Definition: nuklear.h:3938
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3541
NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context *, struct nk_vec2)
struct nk_image img
Definition: nuklear.h:3095
nk_size begin
Definition: nuklear.h:3874
NK_API char * nk_str_at_rune(struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_mouse_button buttons[NK_BUTTON_MAX]
Definition: nuklear.h:3169
struct nk_vec2 clicked_pos
Definition: nuklear.h:3166
Definition: nuklear.h:1843
unsigned char has_preferred_x
Definition: nuklear.h:2856
NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context *, struct nk_rect)
struct nk_window * parent
Definition: nuklear.h:3993
int index
Definition: nuklear.h:3859
Definition: nuklear.h:458
union nk_style_item_data data
Definition: nuklear.h:3379
float border
Definition: nuklear.h:3498
Definition: nuklear.h:691
NK_API nk_uint nk_color_u32(struct nk_color)
NK_API struct nk_vec2 nk_widget_position(struct nk_context *)
struct nk_color background
Definition: nuklear.h:3740
Definition: nuklear.h:463
NK_API int nk_button_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_filter_ascii(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:3819
struct nk_color bottom
Definition: nuklear.h:3015
nk_popup_type
Definition: nuklear.h:474
int prev
Definition: nuklear.h:3957
NK_API int nk_contextual_item_text(struct nk_context *, const char *, int, nk_flags align)
struct nk_page_element * next
Definition: nuklear.h:4109
nk_uint nk_flags
Definition: nuklear.h:405
float at_x
Definition: nuklear.h:3892
Definition: nuklear.h:3368
NK_API int nk_str_insert_text_char(struct nk_str *, int pos, const char *, int)
int count
Definition: nuklear.h:3834
struct nk_window * active
Definition: nuklear.h:4164
struct nk_color highlight
Definition: nuklear.h:3832
struct nk_color color
Definition: nuklear.h:3647
float rounding
Definition: nuklear.h:3702
float at_y
Definition: nuklear.h:3892
Definition: nuklear.h:2946
struct nk_style_text text
Definition: nuklear.h:3781
struct nk_vec2i b
Definition: nuklear.h:3031
nk_handle userdata
Definition: nuklear.h:3474
struct nk_color text_pressed_active
Definition: nuklear.h:3463
struct nk_color label_normal
Definition: nuklear.h:3663
Definition: nuklear.h:3712
struct nk_color combo_border_color
Definition: nuklear.h:3744
NK_API void nk_textedit_text(struct nk_text_edit *, const char *, int total_len)
NK_API void nk_str_delete_chars(struct nk_str *, int pos, int len)
struct nk_popup_buffer buf
Definition: nuklear.h:3934
Definition: nuklear.h:2955
struct nk_color color
Definition: nuklear.h:3374
nk_hash name
Definition: nuklear.h:3935
struct nk_allocator alloc
Definition: nuklear.h:4120
NK_API int nk_str_append_text_runes(struct nk_str *, const nk_rune *, int)
#define NK_INT8
Definition: nuklear.h:337
nk_command_custom_callback callback
Definition: nuklear.h:3106
Definition: nuklear.h:668
std::mutex m
Definition: faio.cpp:21
NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color)
Definition: nuklear.h:2666
NK_INT8 nk_char
Definition: nuklear.h:394
NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color)
Definition: nuklear.h:2001
struct nk_table * tables
Definition: nuklear.h:3987
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3762
NK_API int nk_strtoi(const char *str, const char **endptr)
float max
Definition: nuklear.h:3833
struct nk_vec2 prev
Definition: nuklear.h:3171
enum nk_symbol_type sym_normal
Definition: nuklear.h:3674
Definition: nuklear.h:2000
Definition: nuklear.h:2841
struct nk_table * next
Definition: nuklear.h:4098
struct nk_style_item cursor_hover
Definition: nuklear.h:3527
struct nk_key keys[NK_KEY_MAX]
Definition: nuklear.h:3184
Definition: nuklear.h:4093
NK_API struct nk_style_item nk_style_item_hide(void)
NK_API int nk_combo_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
unsigned short line_thickness
Definition: nuklear.h:3071
NK_API void nk_label(struct nk_context *, const char *, nk_flags align)
nk_byte g
Definition: nuklear.h:453
Definition: nuklear.h:1836
NK_API int nk_style_set_cursor(struct nk_context *, enum nk_style_cursor)
Definition: nuklear.h:3839
int count
Definition: nuklear.h:1801
struct nk_color text_hover
Definition: nuklear.h:3397
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
nk_tree_type
Definition: nuklear.h:476
NK_API int nk_stricmp(const char *s1, const char *s2)
Definition: nuklear.h:3611
NK_API int nk_str_insert_at_rune(struct nk_str *, int pos, const char *, int)
NK_API void nk_plot(struct nk_context *, enum nk_chart_type, const float *values, int count, int offset)
unsigned curve_segment_count
Definition: nuklear.h:987
nk_panel_type
Definition: nuklear.h:3814
short undo_point
Definition: nuklear.h:2827
int cursor
Definition: nuklear.h:2850
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3514
float delta_time_seconds
Definition: nuklear.h:4139
NK_API void nk_contextual_end(struct nk_context *)
NK_API int nk_combo_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
struct nk_command_buffer overlay
Definition: nuklear.h:4156
struct nk_command header
Definition: nuklear.h:2993
NK_API int nk_progress(struct nk_context *, nk_size *cur, nk_size max, int modifyable)
float rounding
Definition: nuklear.h:3532
short y
Definition: nuklear.h:3093
nk_size needed
Definition: nuklear.h:2661
struct nk_style_item normal
Definition: nuklear.h:3657
struct nk_vec2i begin
Definition: nuklear.h:2978
Definition: nuklear.h:1864
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3475
struct nk_buffer buffer
Definition: nuklear.h:2729
float x
Definition: nuklear.h:3882
struct nk_vec2i a
Definition: nuklear.h:3022
struct nk_style_item active
Definition: nuklear.h:3522
struct nk_style_edit edit
Definition: nuklear.h:3791
NK_API int nk_window_is_any_hovered(struct nk_context *)
Definition: nuklear.h:473
Definition: nuklear.h:3168
NK_API struct nk_vec2 nk_vec2iv(const int *xy)
unsigned short h
Definition: nuklear.h:2972
short cy
Definition: nuklear.h:3053
Definition: nuklear.h:969
unsigned char cursor_at_end_of_line
Definition: nuklear.h:2854
float border
Definition: nuklear.h:3751
NK_API int nk_combo_begin_text(struct nk_context *, const char *selected, int, struct nk_vec2 size)
#define NK_BUTTON_BEHAVIOR_STACK_SIZE
Definition: nuklear.h:4022
struct nk_style_button dec_button
Definition: nuklear.h:3508
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
struct nk_style_item pressed_active
Definition: nuklear.h:3453
Definition: nuklear.h:475
nk_button_behavior
Definition: nuklear.h:466
NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context *, struct nk_vec2)
struct nk_vec2 label_padding
Definition: nuklear.h:3733
NK_API int nk_style_pop_float(struct nk_context *)
short y
Definition: nuklear.h:3103
float rounding
Definition: nuklear.h:3629
NK_API struct nk_rect nk_layout_space_bounds(struct nk_context *)
float min_row_height_padding
Definition: nuklear.h:3758
struct nk_table * prev
Definition: nuklear.h:4098
#define NK_INCLUDE_COMMAND_USERDATA
Definition: fa_nuklear.h:14
NK_API int nk_button_image_text_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API int nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
struct nk_vec2i points[1]
Definition: nuklear.h:3073
Definition: nuklear.h:661
struct nk_style_tab tab
Definition: nuklear.h:3795
struct nk_color border_color
Definition: nuklear.h:3419
NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect *, struct nk_context *, struct nk_vec2)
NK_API double nk_strtod(const char *str, const char **endptr)
struct nk_window win
Definition: nuklear.h:4104
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
struct nk_clipboard clip
Definition: nuklear.h:2845
nk_style_cursor
Definition: nuklear.h:2167
struct nk_window * begin
Definition: nuklear.h:4162
NK_API void nk_style_default(struct nk_context *)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect, int down)
#define NK_FLOAT_STACK_SIZE
Definition: nuklear.h:4034
Definition: nuklear.h:1840
struct nk_style_item cursor_hover
Definition: nuklear.h:3553
Definition: nuklear.h:3518
Definition: nuklear.h:2957
Definition: nuklear.h:3824
float y
Definition: nuklear.h:3841
Definition: nuklear.h:3825
int active
Definition: nuklear.h:3957
Definition: nuklear.h:665
NK_API void nk_free(struct nk_context *)
struct nk_color text_normal
Definition: nuklear.h:3592
unsigned short point_count
Definition: nuklear.h:3087
Definition: nuklear.h:496
int buffer_size
Definition: versiongenerate.py:65
Definition: nuklear.h:971
NK_API char * nk_str_at_char(struct nk_str *, int pos)
Definition: nuklear.h:699
Definition: nuklear.h:697
NK_API int nk_button_label_styled(struct nk_context *, const struct nk_style_button *, const char *title)
NK_API struct nk_color nk_rgb(int r, int g, int b)
NK_API int nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
Definition: nuklear.h:474
enum nk_symbol_type sym_active
Definition: nuklear.h:3676
Definition: nuklear.h:500
NK_API void nk_combobox_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int *selected, int count, int item_height, struct nk_vec2 size)
unsigned int has_scrolling
Definition: nuklear.h:3896
int len
Definition: nuklear.h:2730
unsigned int type
Definition: nuklear.h:2658
NK_API void nk_tree_state_pop(struct nk_context *)
NK_API int nk_combo_begin_label(struct nk_context *, const char *selected, struct nk_vec2 size)
NK_API int nk_stricmpn(const char *s1, const char *s2, int n)
Definition: nuklear.h:672
#define NK_UINT32
Definition: nuklear.h:359
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3573
Definition: nuklear.h:3931
unsigned int table_count
Definition: nuklear.h:3988
NK_API int nk_style_push_flags(struct nk_context *, nk_flags *, nk_flags)
int select_start
Definition: nuklear.h:3961
int index
Definition: nuklear.h:3836
struct nk_style_item active
Definition: nuklear.h:3659
NK_API void nk_window_collapse_if(struct nk_context *, const char *name, enum nk_collapse_states, int cond)
Definition: nuklear.h:2008
struct nk_vec2 button_padding
Definition: nuklear.h:3682
Definition: nuklear.h:1862
float contextual_border
Definition: nuklear.h:3753
Definition: nuklear.h:2159
Definition: nuklear.h:1181
char text[NK_INPUT_MAX]
Definition: nuklear.h:3185
NK_API void nk_layout_reset_min_row_height(struct nk_context *)
nk_uint y
Definition: nuklear.h:463
void(* nk_plugin_copy)(nk_handle, const char *, int len)
Definition: nuklear.h:482
unsigned char active
Definition: nuklear.h:2858
float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]
Definition: nuklear.h:3870
NK_API void nk_buffer_push(struct nk_buffer *, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align)
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
NK_API void nk_color_fv(float *rgba_out, struct nk_color)
int state
Definition: nuklear.h:3966
NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input *, struct nk_rect)
Definition: nuklear.h:2835
Definition: nuklear.h:3577
nk_keys
Definition: nuklear.h:660
unsigned arc_segment_count
Definition: nuklear.h:986
#define NK_INT16
Definition: nuklear.h:343
struct nk_command header
Definition: nuklear.h:3092
Definition: nuklear.h:2949
Definition: nuklear.h:3709
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
nk_size end
Definition: nuklear.h:3131
nk_style_item_type
Definition: nuklear.h:3367
const struct nk_cursor * cursor_active
Definition: nuklear.h:3777
Definition: nuklear.h:2676
unsigned circle_segment_count
Definition: nuklear.h:985
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3510
int prev
Definition: nuklear.h:3947
struct nk_command header
Definition: nuklear.h:3020
Definition: nuklear.h:2728
struct nk_command header
Definition: nuklear.h:2970
Definition: nuklear.h:2153
Definition: nuklear.h:2002
struct nk_color label_hover
Definition: nuklear.h:3727
enum nk_symbol_type maximize_symbol
Definition: nuklear.h:3723
Definition: nuklear.h:467
Definition: nuklear.h:3919
struct nk_vec2i b
Definition: nuklear.h:3023
struct nk_style_button button
Definition: nuklear.h:3782
Definition: nuklear.h:1177
struct nk_style_scrollbar scrollh
Definition: nuklear.h:3793
Definition: nuklear.h:1839
NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
NK_API void nk_group_scrolled_end(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:3572
unsigned active_con
Definition: nuklear.h:3939
const float * ratio
Definition: nuklear.h:3863
NK_API int nk_contextual_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
unsigned char single_line
Definition: nuklear.h:2857
Definition: nuklear.h:2012
Definition: nuklear.h:1178
struct nk_color foreground
Definition: nuklear.h:3113
struct nk_vec2 padding
Definition: nuklear.h:3765
Definition: nuklear.h:3881
Definition: nuklear.h:2145
struct nk_table tbl
Definition: nuklear.h:4102
struct nk_panel * parent
Definition: nuklear.h:3902
NK_API void nk_layout_set_min_row_height(struct nk_context *, float height)
struct nk_style_item normal
Definition: nuklear.h:3613
struct nk_vec2 scrollbar
Definition: nuklear.h:2848
NK_API struct nk_vec2 nk_vec2(float x, float y)
unsigned char padding1
Definition: nuklear.h:2859
NK_API void nk_menubar_end(struct nk_context *)
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3606
struct nk_color border_color
Definition: nuklear.h:3392
NK_API void nk_buffer_mark(struct nk_buffer *, enum nk_buffer_allocation_type type)
#define NK_WINDOW_MAX_NAME
Definition: nuklear.h:3909
Definition: nuklear.h:676
nk_uint * offset_x
Definition: nuklear.h:3890
int begin
Definition: nuklear.h:1801
typedef void(ENET_CALLBACK *ENetPacketFreeCallback)(struct _ENetPacket *)
struct nk_config_stack_user_font fonts
Definition: nuklear.h:4083
union nk_page_data data
Definition: nuklear.h:4108
Definition: nuklear.h:2005
NK_API int nk_combo_begin_symbol(struct nk_context *, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_image(struct nk_context *, struct nk_image)
float footer_height
Definition: nuklear.h:3893
Definition: nuklear.h:2156
#define NK_VECTOR_STACK_SIZE
Definition: nuklear.h:4038
Definition: nuklear.h:2961
Definition: nuklear.h:3123
struct nk_draw_null_texture null
Definition: nuklear.h:988
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
Definition: nuklear.h:3372
NK_API int nk_strlen(const char *str)
struct nk_style_item normal
Definition: nuklear.h:3579
float height
Definition: nuklear.h:2484
unsigned short rounding
Definition: nuklear.h:3003
Definition: nuklear.h:692
struct nk_page * next
Definition: nuklear.h:4115
NK_API float nk_strtof(const char *str, const char **endptr)
NK_UINT32 nk_uint
Definition: nuklear.h:400
struct nk_vec2 spacing
Definition: nuklear.h:3683
#define NK_SIZE_TYPE
Definition: nuklear.h:374
struct nk_color bar_active
Definition: nuklear.h:3489
Definition: nuklear.h:2942
Definition: nuklear.h:3737
struct nk_color cursor_text_normal
Definition: nuklear.h:3588
NK_API struct nk_color nk_rgb_fv(const float *rgb)
NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name)
int tree_depth
Definition: nuklear.h:3869
NK_API void nk_draw_text(struct nk_command_buffer *, struct nk_rect, const char *text, int len, const struct nk_user_font *, struct nk_color, struct nk_color)
float b
Definition: nuklear.h:454
enum nk_allocation_type type
Definition: nuklear.h:4121
struct nk_command header
Definition: nuklear.h:3084
unsigned int seq
Definition: nuklear.h:3970
struct nk_buffer memory
Definition: nuklear.h:4134
nk_text_align
Definition: nuklear.h:1861
NK_API struct nk_color nk_hsva_iv(const int *hsva)
NK_API void nk_combobox(struct nk_context *, const char **items, int count, int *selected, int item_height, struct nk_vec2 size)
struct nk_scroll scrollbar
Definition: nuklear.h:3951
NK_API void nk_buffer_reset(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API int nk_str_insert_text_runes(struct nk_str *, int pos, const nk_rune *, int)
enum nk_symbol_type sym_maximize
Definition: nuklear.h:3698
NK_API void nk_textedit_delete_selection(struct nk_text_edit *)
int active
Definition: nuklear.h:3878
struct nk_window * end
Definition: nuklear.h:4163
Definition: nuklear.h:680
Definition: nuklear.h:2151
struct nk_rect item
Definition: nuklear.h:3868
NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color)
NK_API int nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *, nk_flags)
float item_offset
Definition: nuklear.h:3866
Definition: nuklear.h:461
struct nk_color text
Definition: nuklear.h:3690
NK_API struct nk_color nk_rgba(int r, int g, int b, int a)
Definition: nuklear.h:2673
NK_API void * nk_buffer_memory(struct nk_buffer *)
nk_text_edit_type
Definition: nuklear.h:2833
NK_API void nk_textedit_init_fixed(struct nk_text_edit *, void *memory, nk_size size)
NK_API int nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
unsigned short h
Definition: nuklear.h:3005
#define NK_SATURATE(x)
Definition: nuklear.h:4179
struct nk_style_slider slider
Definition: nuklear.h:3788
struct nk_color label_active
Definition: nuklear.h:3621
Definition: nuklear.h:2142
Definition: nuklear.h:3853
NK_API void nk_stroke_curve(struct nk_command_buffer *, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color)
float popup_border
Definition: nuklear.h:3757
NK_API int nk_button_image(struct nk_context *, struct nk_image img)
NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region)
nk_hash name
Definition: nuklear.h:3944
float border
Definition: nuklear.h:3679
nk_size parent
Definition: nuklear.h:3875
NK_API int nk_combo(struct nk_context *, const char **items, int count, int selected, int item_height, struct nk_vec2 size)
Definition: nuklear.h:3969
Definition: nuklear.h:2163
Definition: nuklear.h:1182
nk_byte a
Definition: nuklear.h:453
NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a)
NK_API void nk_str_clear(struct nk_str *)
float rounding
Definition: nuklear.h:3651
float a[2]
Definition: nuklear.h:3064
#define NK_TEXTEDIT_UNDOCHARCOUNT
Definition: nuklear.h:2807
NK_API const void * nk_buffer_memory_const(const struct nk_buffer *)
#define nk_ptr_add_const(t, p, i)
Definition: nuklear.h:4196
Definition: nuklear.h:2956
NK_API void nk_buffer_init_fixed(struct nk_buffer *, void *memory, nk_size size)
float x
Definition: nuklear.h:457
Definition: nuklear.h:977
NK_API void nk_layout_row_template_begin(struct nk_context *, float row_height)
Definition: nuklear.h:2140
NK_API void nk_popup_close(struct nk_context *)
NK_API void nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, float x1, float y1, float line_thickness, struct nk_color)
Definition: nuklear.h:2152
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3568
short x
Definition: nuklear.h:3114
nk_uint nk_rune
Definition: nuklear.h:406
struct nk_color text_active
Definition: nuklear.h:3398
struct nk_page_element * freelist
Definition: nuklear.h:4124
struct nk_window * next
Definition: nuklear.h:3991
NK_API struct nk_color nk_color_picker(struct nk_context *, struct nk_color, enum nk_color_format)
struct nk_vec2 combo_padding
Definition: nuklear.h:3768
NK_API int nk_str_append_text_utf8(struct nk_str *, const char *, int)
struct nk_color text_hover
Definition: nuklear.h:3427
NK_API void nk_text_colored(struct nk_context *, const char *, int, nk_flags, struct nk_color)
int end
Definition: nuklear.h:1801
struct nk_config_stack_flags flags
Definition: nuklear.h:4081
nk_panel_set
Definition: nuklear.h:3823
unsigned short w
Definition: nuklear.h:3115
float x
Definition: nuklear.h:3841
struct nk_image image
Definition: nuklear.h:3373
float cursor_rounding
Definition: nuklear.h:3535
NK_API int nk_checkbox_flags_text(struct nk_context *, const char *, int, unsigned int *flags, unsigned int value)
Definition: nuklear.h:4101
NK_API int nk_button_image_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img)
unsigned short line_thickness
Definition: nuklear.h:2985
int total_height
Definition: nuklear.h:1803
NK_API struct nk_rect nk_rect(float x, float y, float w, float h)
struct nk_vec2 touch_padding
Definition: nuklear.h:3406
Definition: nuklear.h:3923
nk_orientation
Definition: nuklear.h:468
NK_API void nk_style_show_cursor(struct nk_context *)
struct nk_color text_background
Definition: nuklear.h:3464
struct nk_window * prev
Definition: nuklear.h:3992
int cursor
Definition: nuklear.h:3948
struct nk_vec2 min_size
Definition: nuklear.h:3763
struct nk_command header
Definition: nuklear.h:3052
struct nk_color color
Definition: nuklear.h:3048
float spacing
Definition: nuklear.h:3435
struct nk_style_item normal
Definition: nuklear.h:3714
Definition: nuklear.h:2943
struct nk_vec2 padding
Definition: nuklear.h:3732
nk_widget_layout_states
Definition: nuklear.h:1830
Definition: nuklear.h:2950
struct nk_style_scrollbar scrollv
Definition: nuklear.h:3794
NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value)
Definition: nuklear.h:3544
NK_API int nk_style_push_font(struct nk_context *, const struct nk_user_font *)
enum nk_anti_aliasing line_AA
Definition: nuklear.h:983
struct nk_style_item active
Definition: nuklear.h:3391
nk_collapse_states
Definition: nuklear.h:469
short redo_point
Definition: nuklear.h:2828
NK_API const char * nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len)
Definition: nuklear.h:499
Definition: nuklear.h:456
NK_API int nk_chart_begin_colored(struct nk_context *, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max)
NK_API void nk_style_hide_cursor(struct nk_context *)
NK_API int nk_menu_begin_image_text(struct nk_context *, const char *, int, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:3849
struct nk_color border_color
Definition: nuklear.h:3484
Definition: nuklear.h:1833
Definition: nuklear.h:2144
NK_API int nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *, const char *title, nk_flags)
struct nk_color color
Definition: nuklear.h:3006
NK_API void nk_str_remove_runes(struct nk_str *str, int len)
struct nk_vec2 spacing
Definition: nuklear.h:3761
float item_width
Definition: nuklear.h:3864
Definition: nuklear.h:2945
Definition: nuklear.h:2169
Definition: nuklear.h:3479
#define NK_ALIGN_PTR(x, mask)
Definition: nuklear.h:4217
struct nk_color color
Definition: nuklear.h:3025
int cursor_visible
Definition: nuklear.h:3779
NK_API int nk_widget_has_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
#define NK_CLAMP(i, v, x)
Definition: nuklear.h:317
struct nk_style_combo combo
Definition: nuklear.h:3796
struct nk_style_property property
Definition: nuklear.h:3790
unsigned short region[4]
Definition: nuklear.h:461
NK_API void nk_input_begin(struct nk_context *)
int length
Definition: nuklear.h:3959
struct nk_window * win
Definition: nuklear.h:3932
struct nk_color contextual_border_color
Definition: nuklear.h:3745
Definition: nuklear.h:3028
NK_API int nk_option_text(struct nk_context *, const char *, int, int active)
void * ptr
Definition: nuklear.h:460
struct nk_menu_state menu
Definition: nuklear.h:3898
NK_API void nk_stroke_rect(struct nk_command_buffer *, struct nk_rect, float rounding, float line_thickness, struct nk_color)
NK_API int nk_menu_begin_symbol_text(struct nk_context *, const char *, int, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API void nk_push_scissor(struct nk_command_buffer *, struct nk_rect)
NK_API const struct nk_command * nk__begin(struct nk_context *)
float min_height
Definition: nuklear.h:3861
NK_API nk_flags nk_chart_push_slot(struct nk_context *, float, int)
Definition: nuklear.h:2147
nk_edit_flags
Definition: nuklear.h:1996
#define NK_INBOX(px, py, x, y, w, h)
Definition: nuklear.h:4183
int value
Definition: der_length_ia5_string.c:21
#define nk_vec2_sub(a, b)
Definition: nuklear.h:4190
Definition: nuklear.h:470
NK_API int nk_str_append_str_char(struct nk_str *, const char *)
float indent
Definition: nuklear.h:3703
Definition: nuklear.h:700
struct nk_color selected_color
Definition: nuklear.h:3646
unsigned char initialized
Definition: nuklear.h:2855
Definition: nuklear.h:2148
Definition: nuklear.h:1180
NK_API int nk_input_is_key_down(const struct nk_input *, enum nk_keys)
Definition: nuklear.h:501
NK_API int nk_window_is_hovered(struct nk_context *)
short x
Definition: nuklear.h:3093
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
#define NK_PI
Definition: nuklear.h:4174
struct nk_cursor * cursor_last
Definition: nuklear.h:3778
nk_size last
Definition: nuklear.h:3131
NK_API int nk_filter_decimal(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:2018
Definition: nuklear.h:469
float height
Definition: nuklear.h:3116
NK_API int nk_filter_binary(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_init(struct nk_context *, struct nk_allocator *, const struct nk_user_font *)
Definition: nuklear.h:2149
NK_API int nk_radio_label(struct nk_context *, const char *, int *active)
struct nk_vec2 spacing
Definition: nuklear.h:3734
NK_API void nk_contextual_close(struct nk_context *)
short y
Definition: nuklear.h:3038
NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
void(* nk_command_custom_callback)(void *canvas, short x, short y, unsigned short w, unsigned short h, nk_handle callback_data)
Definition: nuklear.h:3099
NK_API void nk_textedit_init(struct nk_text_edit *, struct nk_allocator *, nk_size size)
const struct nk_cursor * cursors[NK_CURSOR_COUNT]
Definition: nuklear.h:3776
struct nk_vec2 spacing
Definition: nuklear.h:3502
const struct nk_draw_vertex_layout_element * vertex_layout
Definition: nuklear.h:989
struct nk_style_chart chart
Definition: nuklear.h:3792
#define NK_UTF_SIZE
Definition: nuklear.h:255
struct nk_vec2 popup_padding
Definition: nuklear.h:3767
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
short delete_length
Definition: nuklear.h:2820
NK_API void nk_fill_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, struct nk_color)
NK_API const char * nk_str_get_const(const struct nk_str *)
NK_API int nk_textedit_cut(struct nk_text_edit *)
Definition: nuklear.h:972
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
Definition: nuklear.h:3686
struct nk_color cursor_text_hover
Definition: nuklear.h:3589
NK_API int nk_button_image_label_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_combo_separator(struct nk_context *, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size)
NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color)
float border
Definition: nuklear.h:3558
float rounding
Definition: nuklear.h:3499
NK_API void nk_stroke_polyline(struct nk_command_buffer *, float *points, int point_count, float line_thickness, struct nk_color col)
NK_API void nk_text_wrap_colored(struct nk_context *, const char *, int, struct nk_color)
NK_API enum nk_widget_layout_states nk_widget(struct nk_rect *, const struct nk_context *)
nk_edit_events
Definition: nuklear.h:2017
NK_API struct nk_vec2 nk_rect_pos(struct nk_rect)
Definition: nuklear.h:3848
struct nk_text_undo_state undo
Definition: nuklear.h:2861
NK_API int nk_input_is_mouse_released(const struct nk_input *, enum nk_buttons)
Definition: nuklear.h:2157
NK_API void nk_property_int(struct nk_context *, const char *name, int min, int *val, int max, int step, float inc_per_pixel)
struct nk_style_button button
Definition: nuklear.h:3673
#define NK_SCROLLBAR_HIDING_TIMEOUT
Definition: nuklear.h:263
enum nk_symbol_type sym_right
Definition: nuklear.h:3625
Definition: nuklear.h:3774
NK_API void nk_color_hex_rgba(char *output, struct nk_color)
#define NK_MIN(a, b)
Definition: nuklear.h:315
Definition: nuklear.h:3917
struct nk_vec2 group_padding
Definition: nuklear.h:3766
Definition: nuklear.h:468
nk_handle userdata
Definition: nuklear.h:485
NK_API void nk_style_load_cursor(struct nk_context *, enum nk_style_cursor, const struct nk_cursor *)
unsigned int size
Definition: nuklear.h:4114
Definition: nuklear.h:455
Definition: nuklear.h:457
NK_API int nk_input_is_mouse_pressed(const struct nk_input *, enum nk_buttons)
Definition: nuklear.h:2158
struct nk_style_item cursor_normal
Definition: nuklear.h:3493
#define NK_VALUE_PAGE_CAPACITY
Definition: nuklear.h:4090
Definition: nuklear.h:474
NK_API void nk_push_custom(struct nk_command_buffer *, struct nk_rect, nk_command_custom_callback, nk_handle usr)
Definition: nuklear.h:3076
Definition: nuklear.h:490
enum nk_style_header_align align
Definition: nuklear.h:3731
NK_API int nk_str_len_char(struct nk_str *)
int active
Definition: nuklear.h:2677
Definition: nuklear.h:2172
unsigned int clicked
Definition: nuklear.h:3181
NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input *, struct nk_rect)
void * ptr
Definition: nuklear.h:2681
Definition: nuklear.h:2143
NK_API const char * nk_style_get_color_by_name(enum nk_style_colors)
void(* nk_query_font_glyph_f)(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
Definition: nuklear.h:2464
Definition: nuklear.h:3852
NK_API void nk_stroke_arc(struct nk_command_buffer *, float cx, float cy, float radius, float a_min, float a_max, float line_thickness, struct nk_color)
Definition: nuklear.h:975
Definition: nuklear.h:2824
Definition: nuklear.h:662
nk_size vertex_alignment
Definition: nuklear.h:991
NK_API void nk_tooltip_end(struct nk_context *)
Definition: nuklear.h:679
Definition: nuklear.h:502
struct nk_color border_color
Definition: nuklear.h:3645
struct nk_style_item cursor_normal
Definition: nuklear.h:3526
unsigned short h
Definition: nuklear.h:3040
Definition: nuklear.h:2020
Definition: nuklear.h:503
short w
Definition: nuklear.h:458
NK_API void nk_spacing(struct nk_context *, int cols)
Definition: nuklear.h:467
Definition: nuklear.h:2656
Definition: nuklear.h:682
struct nk_color text_background
Definition: nuklear.h:3395
float y
Definition: nuklear.h:455
NK_API struct nk_color nk_rgba_hex(const char *rgb)
struct nk_vec2i points[1]
Definition: nuklear.h:3080
struct nk_vec2 padding
Definition: nuklear.h:3704
struct nk_command header
Definition: nuklear.h:3077
struct nk_style_item active
Definition: nuklear.h:3615
GLuint texture
Definition: sdl2backend.cpp:527
NK_API int nk_button_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags text_alignment)
#define NK_STATIC_ASSERT(exp)
Definition: nuklear.h:304
NK_API struct nk_image nk_subimage_ptr(void *, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API void nk_text_wrap(struct nk_context *, const char *, int)
NK_API struct nk_image nk_image_handle(nk_handle)
NK_API struct nk_image nk_image_ptr(void *)
short y
Definition: nuklear.h:3046
NK_API float nk_window_get_width(const struct nk_context *)
NK_API int nk_image_is_subimage(const struct nk_image *img)
nk_size begin
Definition: nuklear.h:3131
struct nk_command header
Definition: nuklear.h:3002
Definition: nuklear.h:973
Definition: nuklear.h:1179
struct nk_context * ctx
Definition: nuklear.h:1804
unsigned char mode
Definition: nuklear.h:2853
struct nk_style_item hover
Definition: nuklear.h:3482
unsigned short h
Definition: nuklear.h:3115
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
struct nk_color text_hover_active
Definition: nuklear.h:3462
NK_API int nk_selectable_label(struct nk_context *, const char *, nk_flags align, int *value)
struct nk_style_button tab_minimize_button
Definition: nuklear.h:3694
struct nk_vec2 padding
Definition: nuklear.h:3607
NK_API struct nk_color nk_hsva(int h, int s, int v, int a)
struct nk_vec2 spacing
Definition: nuklear.h:3705
#define NK_STYLE_ITEM_STACK_SIZE
Definition: nuklear.h:4030
Definition: nuklear.h:669
NK_API int nk_str_insert_text_utf8(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:3387
NK_API void nk_tooltip(struct nk_context *, const char *)
Definition: nuklear.h:2682
struct nk_color text_active
Definition: nuklear.h:3428
#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
Definition: nuklear.h:3808
nk_plugin_alloc alloc
Definition: nuklear.h:486
NK_API void nk_combo_close(struct nk_context *)
struct nk_color text_hover
Definition: nuklear.h:3593
NK_API int nk_radio_text(struct nk_context *, const char *, int, int *active)
NK_API void nk_buffer_clear(struct nk_buffer *)
Definition: nuklear.h:3886
nk_uint scroll_value
Definition: nuklear.h:1806
short undo_char_point
Definition: nuklear.h:2829
enum nk_symbol_type sym_hover
Definition: nuklear.h:3675
enum nk_symbol_type close_symbol
Definition: nuklear.h:3721
int id
Definition: nuklear.h:460
Definition: nuklear.h:2481
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *)
Definition: nuklear.h:465
nk_uint * offset_y
Definition: nuklear.h:3891
struct nk_command header
Definition: nuklear.h:3069
struct nk_color label_hover
Definition: nuklear.h:3620
Definition: nuklear.h:1838
nk_size end
Definition: nuklear.h:3877
int select_end
Definition: nuklear.h:2852
NK_API const char * nk_str_at_char_const(const struct nk_str *, int pos)
struct nk_configuration_stacks stacks
Definition: nuklear.h:4138
struct nk_style_item cursor_active
Definition: nuklear.h:3554
Definition: nuklear.h:2019
Definition: nuklear.h:3019
NK_API nk_handle nk_handle_id(int)
NK_API int nk_combo_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned short h
Definition: nuklear.h:3012
NK_UINT8 nk_uchar
Definition: nuklear.h:395
int active
Definition: nuklear.h:3947
NK_API struct nk_color nk_rgb_f(float r, float g, float b)
Definition: nuklear.h:2840
enum nk_allocation_type type
Definition: nuklear.h:2687
float r
Definition: nuklear.h:454
nk_window_flags
Definition: nuklear.h:3913
short x
Definition: nuklear.h:3011
nk_chart_type
Definition: nuklear.h:471
float x
Definition: nuklear.h:455
struct nk_color symbol_hover
Definition: nuklear.h:3669
struct nk_mouse mouse
Definition: nuklear.h:3191
enum nk_chart_type type
Definition: nuklear.h:3830
Definition: nuklear.h:498
struct nk_rect bounds
Definition: nuklear.h:3889
Definition: nuklear.h:2137
Definition: nuklear.h:2667
NK_API int nk_contextual_item_label(struct nk_context *, const char *, nk_flags align)
#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)
Definition: nuklear.h:4049
struct nk_color border_color
Definition: nuklear.h:3549
NK_API int nk_list_view_begin(struct nk_context *, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count)
float rounding
Definition: nuklear.h:3604
nk_size size
Definition: nuklear.h:4126
struct nk_vec2 padding
Definition: nuklear.h:3469
NK_API void nk_stroke_polygon(struct nk_command_buffer *, float *, int point_count, float line_thickness, struct nk_color)
unsigned combo_count
Definition: nuklear.h:3937
NK_API void nk_popup_end(struct nk_context *)
unsigned int size
Definition: nuklear.h:4095
int build
Definition: nuklear.h:4159
struct nk_page * pages
Definition: nuklear.h:4123
NK_API void nk_input_motion(struct nk_context *, int x, int y)
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
Definition: nuklear.h:3444
NK_API int nk_color_pick(struct nk_context *, struct nk_color *, enum nk_color_format)
Definition: nuklear.h:2948
NK_API int nk_utf_len(const char *, int byte_len)
float g
Definition: nuklear.h:454
Definition: nuklear.h:974
NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading)
Definition: nuklear.h:1837
nk_size vertex_size
Definition: nuklear.h:990
unsigned short w
Definition: nuklear.h:3040
Definition: nuklear.h:1841
NK_API struct nk_color nk_hsva_fv(const float *hsva)
Definition: nuklear.h:462
Definition: nuklear.h:696
nk_size cap
Definition: nuklear.h:4127
Definition: nuklear.h:2003
Definition: nuklear.h:1176
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3509
NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color)
Definition: nuklear.h:4113
struct nk_keyboard keyboard
Definition: nuklear.h:3190
unsigned short rounding
Definition: nuklear.h:2994
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3476
#define NK_UINT16
Definition: nuklear.h:346
Definition: nuklear.h:475
unsigned short w
Definition: nuklear.h:461
Definition: nuklear.h:3044
unsigned short w
Definition: nuklear.h:3047
#define NK_TEXTEDIT_UNDOSTATECOUNT
Definition: nuklear.h:2803
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3639
NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value)
struct nk_style_scrollbar scrollbar
Definition: nuklear.h:3583
struct nk_color bar_normal
Definition: nuklear.h:3487
nk_flags last_widget_state
Definition: nuklear.h:4136
Definition: nuklear.h:3927
#define nk_foreach(c, ctx)
Definition: nuklear.h:1011
struct nk_color color
Definition: nuklear.h:3831
struct nk_command header
Definition: nuklear.h:3045
int(* nk_plugin_filter)(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:480
struct nk_style_item normal_active
Definition: nuklear.h:3451
Definition: nuklear.h:476
NK_API float nk_window_get_height(const struct nk_context *)
NK_API float nk_widget_height(struct nk_context *)
NK_API int nk_menu_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
NK_API int nk_slide_int(struct nk_context *, int min, int val, int max, int step)
Definition: nuklear.h:3857
NK_API int nk_filter_oct(const struct nk_text_edit *, nk_rune unicode)
float filled
Definition: nuklear.h:3867
#define NK_LEN(a)
Definition: nuklear.h:4180
NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
Definition: nuklear.h:2947
Definition: nuklear.h:3109
Definition: nuklear.h:693
NK_API int nk_slider_float(struct nk_context *, float min, float *val, float max, float step)
NK_API int nk_window_is_hidden(struct nk_context *, const char *)
NK_API void nk_fill_triangle(struct nk_command_buffer *, float x0, float y0, float x1, float y1, float x2, float y2, struct nk_color)
Definition: nuklear.h:1999
short cx
Definition: nuklear.h:3053
#define NK_INTERN
Definition: nuklear.h:286
struct nk_command_buffer buffer
Definition: nuklear.h:3977
NK_API int nk_slider_int(struct nk_context *, int min, int *val, int max, int step)
nk_size allocated
Definition: nuklear.h:2660
nk_hash name
Definition: nuklear.h:3963
Definition: nuklear.h:468
struct nk_vec2i end
Definition: nuklear.h:2979
NK_API int nk_contextual_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
unsigned con_count
Definition: nuklear.h:3938
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
NK_API int nk_item_is_any_active(struct nk_context *)
NK_API void nk_label_colored_wrap(struct nk_context *, const char *, struct nk_color)
struct nk_style_toggle checkbox
Definition: nuklear.h:3786
void(* draw_end)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3411
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
NK_API struct nk_style_item nk_style_item_color(struct nk_color)
Definition: nuklear.h:2969
#define SEEK_SET
Definition: zconf.h:388
Definition: nuklear.h:677
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
NK_API int nk_button_push_behavior(struct nk_context *, enum nk_button_behavior)
#define nk_ptr_add(t, p, i)
Definition: nuklear.h:4195
NK_API float nk_slide_float(struct nk_context *, float min, float val, float max, float step)
NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color)
Definition: nuklear.h:667
NK_API void nk_fill_polygon(struct nk_command_buffer *, float *, int point_count, struct nk_color)
nk_size size
Definition: nuklear.h:2681
short x
Definition: nuklear.h:2996
NK_API float nk_widget_width(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:3523
Definition: nuklear.h:1867
Definition: nuklear.h:3655
#define nk_vec2_add(a, b)
Definition: nuklear.h:4191
NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input *, struct nk_rect)
float cursor_border
Definition: nuklear.h:3534
NK_API int nk_chart_begin(struct nk_context *, enum nk_chart_type, int num, float min, float max)
NK_API int nk_style_pop_vec2(struct nk_context *)
Definition: nuklear.h:2173
struct nk_config_stack_style_item style_items
Definition: nuklear.h:4078
NK_API nk_size nk_buffer_total(struct nk_buffer *)
nk_size size
Definition: nuklear.h:2659
Definition: nuklear.h:681
NK_API nk_handle nk_handle_ptr(void *)
unsigned short h
Definition: nuklear.h:3104
unsigned int clicked
Definition: nuklear.h:3165
struct nk_style_item cursor_active
Definition: nuklear.h:3495
NK_API void nk_window_show(struct nk_context *, const char *name, enum nk_show_states)
struct nk_style style
Definition: nuklear.h:4133
Definition: nuklear.h:1872
NK_API void nk_tree_pop(struct nk_context *)
float range
Definition: nuklear.h:3833
const struct nk_user_font * font
Definition: nuklear.h:3111
Definition: gtest_output_test_.cc:544
NK_API void nk_textedit_undo(struct nk_text_edit *)
NK_API unsigned nk_check_flags_text(struct nk_context *, const char *, int, unsigned int flags, unsigned int value)
unsigned int count
Definition: nuklear.h:4167
struct nk_popup_state popup
Definition: nuklear.h:3983
NK_API float nk_layout_ratio_from_pixel(struct nk_context *, float pixel_width)
Definition: nuklear.h:1870
struct nk_vec2 padding
Definition: nuklear.h:3404
NK_API nk_flags nk_edit_buffer(struct nk_context *, nk_flags, struct nk_text_edit *, nk_plugin_filter)
float y
Definition: nuklear.h:457
int active
Definition: nuklear.h:3936
short x
Definition: nuklear.h:456
struct nk_color right
Definition: nuklear.h:3016
Definition: nuklear.h:3820
NK_API int nk_style_pop_style_item(struct nk_context *)
nk_handle userdata
Definition: nuklear.h:2482
Definition: nuklear.h:497
uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
Definition: adler32.c:60
struct nk_style_item hover
Definition: nuklear.h:3547
nk_plugin_filter filter
Definition: nuklear.h:2847
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3540
struct nk_style_item normal
Definition: nuklear.h:3546
NK_API int nk_checkbox_flags_label(struct nk_context *, const char *, unsigned int *flags, unsigned int value)
struct nk_color symbol_active
Definition: nuklear.h:3670
nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]
Definition: nuklear.h:2826
float scrollbar_hiding_timer
Definition: nuklear.h:3979
NK_API int nk_str_append_str_utf8(struct nk_str *, const char *)
nk_text_alignment
Definition: nuklear.h:1869
Definition: nuklear.h:2941
#define NK_API
Definition: nuklear.h:282
struct nk_rect bounds
Definition: nuklear.h:3975
Definition: nuklear.h:2834
unsigned short w
Definition: nuklear.h:3104
NK_API int nk_window_is_active(struct nk_context *, const char *)
Definition: nuklear.h:471
unsigned short line_thickness
Definition: nuklear.h:3039
Definition: nuklear.h:466
struct nk_style_window_header header
Definition: nuklear.h:3738
Definition: nuklear.h:3710
float global_alpha
Definition: nuklear.h:982
struct nk_command header
Definition: nuklear.h:3010
Definition: nuklear.h:3101
struct nk_color color
Definition: nuklear.h:2998
Definition: nuklear.h:470
unsigned capacity
Definition: nuklear.h:4125
NK_API int nk_style_push_color(struct nk_context *, struct nk_color *, struct nk_color)
struct nk_vec2 padding
Definition: nuklear.h:3652
Definition: nuklear.h:2006
NK_API void nk_style_load_all_cursors(struct nk_context *, struct nk_cursor *)
struct nk_vec2 touch_padding
Definition: nuklear.h:3470
struct nk_color color
Definition: nuklear.h:3070
struct nk_style_item fixed_background
Definition: nuklear.h:3739
Definition: nuklear.h:2139
nk_byte b
Definition: nuklear.h:453
NK_API int nk_input_has_mouse_click(const struct nk_input *, enum nk_buttons)
NK_API int nk_combo_begin_color(struct nk_context *, struct nk_color color, struct nk_vec2 size)
NK_API void nk_str_free(struct nk_str *)
int show_buttons
Definition: nuklear.h:3506
NK_API int nk_option_label(struct nk_context *, const char *, int active)
nk_size last
Definition: nuklear.h:3876
float border
Definition: nuklear.h:3533
nk_allocation_type
Definition: nuklear.h:2665
void(* nk_plugin_free)(nk_handle, void *old)
Definition: nuklear.h:479
struct nk_vec2i a
Definition: nuklear.h:3030
nk_plugin_paste paste
Definition: nuklear.h:2813
NK_API int nk_combo_begin_image_label(struct nk_context *, const char *selected, struct nk_image, struct nk_vec2 size)
struct nk_color cursor_border_color
Definition: nuklear.h:3555
nk_size next
Definition: nuklear.h:2963
struct nk_color color
Definition: nuklear.h:3078
struct nk_style_item background
Definition: nuklear.h:3688
Definition: nuklear.h:2154
NK_API void nk_textedit_free(struct nk_text_edit *)
struct nk_scroll scrollbar
Definition: nuklear.h:3976
NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color)
struct nk_buffer * base
Definition: nuklear.h:3127
float(* nk_text_width_f)(nk_handle, float h, const char *, int len)
Definition: nuklear.h:2463
int use_clipping
Definition: nuklear.h:3129
NK_API struct nk_command_buffer * nk_window_get_canvas(struct nk_context *)
NK_API int nk_checkbox_text(struct nk_context *, const char *, int, int *active)
nk_uint nk_hash
Definition: nuklear.h:404
NK_API int nk_str_len(struct nk_str *)
nk_command_type
Definition: nuklear.h:2938
NK_API nk_flags nk_edit_string(struct nk_context *, nk_flags, char *buffer, int *len, int max, nk_plugin_filter)
NK_API void nk_edit_unfocus(struct nk_context *)
unsigned int old
Definition: nuklear.h:3946
nk_size calls
Definition: nuklear.h:2662
Definition: nuklear.h:686
Definition: nuklear.h:1866
struct nk_vec2 pos
Definition: nuklear.h:3170
Definition: nuklear.h:2671
struct nk_style_item hover
Definition: nuklear.h:3614
Definition: nuklear.h:684
NK_API int nk_combo_item_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags alignment)
NK_API int nk_combo_begin_symbol_text(struct nk_context *, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:2165
#define NK_INPUT_MAX
Definition: nuklear.h:257
NK_API int nk_menu_begin_symbol_label(struct nk_context *, const char *, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:2013
NK_API void nk_buffer_free(struct nk_buffer *)
Definition: nuklear.h:2951
struct nk_style_item hover
Definition: nuklear.h:3715
NK_API struct nk_color nk_hsv_f(float h, float s, float v)
nk_hash name
Definition: nuklear.h:3971
struct nk_style_item cursor_active
Definition: nuklear.h:3528
struct nk_color color
Definition: nuklear.h:3041
struct nk_style_item normal
Definition: nuklear.h:3481
NK_API int nk_button_symbol(struct nk_context *, enum nk_symbol_type)
NK_API int nk_checkbox_label(struct nk_context *, const char *, int *active)
int use_pool
Definition: nuklear.h:4160
enum nk_symbol_type minimize_symbol
Definition: nuklear.h:3722
struct nk_vec2 scroll_delta
Definition: nuklear.h:3173
enum nk_panel_type type
Definition: nuklear.h:3933
NK_API int nk_window_is_closed(struct nk_context *, const char *)
struct nk_vec2 padding
Definition: nuklear.h:3433
Definition: nuklear.h:469
Definition: nuklear.h:685
NK_API int nk_group_begin(struct nk_context *, const char *title, nk_flags)
struct nk_rect header
Definition: nuklear.h:3940
float h
Definition: nuklear.h:3882
Definition: nuklear.h:3091
Definition: nuklear.h:3036
NK_API void nk_buffer_info(struct nk_memory_status *, struct nk_buffer *)
NK_API const char * nk_str_at_const(const struct nk_str *, int pos, nk_rune *unicode, int *len)
struct nk_color symbol_normal
Definition: nuklear.h:3668
struct nk_vec2 delta
Definition: nuklear.h:3172
Definition: nuklear.h:4077
#define NK_COLOR_STACK_SIZE
Definition: nuklear.h:4046
float row_padding
Definition: nuklear.h:3608
int down
Definition: nuklear.h:3164
struct nk_style_item normal
Definition: nuklear.h:3416
enum nk_panel_row_layout_type type
Definition: nuklear.h:3858
NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color)
Definition: nuklear.h:981
#define NK_BETWEEN(x, a, b)
Definition: nuklear.h:4182
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API void nk_clear(struct nk_context *)
struct nk_color cursor_border_color
Definition: nuklear.h:3529
Definition: nuklear.h:2141
Definition: nuklear.h:674
float w
Definition: nuklear.h:457
struct nk_color border_color
Definition: nuklear.h:3616
NK_API void nk_menu_end(struct nk_context *)
#define NK_CONTAINER_OF(ptr, type, member)
Definition: nuklear.h:4223
struct nk_style_item hover
Definition: nuklear.h:3447
NK_API int nk_selectable_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int *value)
struct nk_style_button minimize_button
Definition: nuklear.h:3720
struct nk_style_item cursor_normal
Definition: nuklear.h:3552
NK_API nk_flags nk_chart_push(struct nk_context *, float)
NK_API unsigned nk_check_flags_label(struct nk_context *, const char *, unsigned int flags, unsigned int value)
float rounding
Definition: nuklear.h:3468
NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
NK_API int nk_input_is_key_released(const struct nk_input *, enum nk_keys)
Definition: nuklear.h:495
struct nk_color cursor_hover
Definition: nuklear.h:3587
struct nk_style_item hover
Definition: nuklear.h:3521
Definition: nuklear.h:2983
Definition: nuklear.h:3068
enum nk_command_type type
Definition: nuklear.h:2962
float rounding
Definition: nuklear.h:3680
struct nk_style_button inc_button
Definition: nuklear.h:3566
struct nk_color text_active
Definition: nuklear.h:3594
NK_API struct nk_rect nk_widget_bounds(struct nk_context *)
struct nk_config_stack_vec2 vectors
Definition: nuklear.h:4080
float border
Definition: nuklear.h:3701
Definition: nuklear.h:473
Definition: nuklear.h:2944
short y
Definition: nuklear.h:2971
NK_API void nk_window_show_if(struct nk_context *, const char *name, enum nk_show_states, int cond)
NK_API int nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
nk_color_format
Definition: nuklear.h:473
struct nk_command header
Definition: nuklear.h:3110
float combo_border
Definition: nuklear.h:3752
struct nk_color cursor_normal
Definition: nuklear.h:3586
struct nk_command header
Definition: nuklear.h:3102
nk_hash keys[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:4096
NK_API struct nk_color nk_hsv_iv(const int *hsv)
NK_API int nk_menu_begin_image(struct nk_context *, const char *, struct nk_image, struct nk_vec2 size)
struct nk_color popup_border_color
Definition: nuklear.h:3743
NK_API int nk_menu_begin_image_label(struct nk_context *, const char *, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:4107
NK_API int nk_str_insert_at_char(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:1832
Definition: nuklear.h:2811
NK_API int nk_selectable_text(struct nk_context *, const char *, int, nk_flags align, int *value)
NK_UINT16 nk_ushort
Definition: nuklear.h:398
Definition: nuklear.h:3083
Definition: nuklear.h:1863
Definition: nuklear.h:3921
unsigned int old
Definition: nuklear.h:3965
nk_size size
Definition: nuklear.h:2699
enum nk_panel_type type
Definition: nuklear.h:3887
NK_API int nk_input_is_mouse_down(const struct nk_input *, enum nk_buttons)
NK_API nk_size nk_prog(struct nk_context *, nk_size cur, nk_size max, int modifyable)
NK_API int nk_filter_float(const struct nk_text_edit *, nk_rune unicode)
struct nk_vec2i begin
Definition: nuklear.h:2986
Definition: nuklear.h:3915
nk_handle callback_data
Definition: nuklear.h:3105
NK_API void nk_input_end(struct nk_context *)
NK_API int nk_button_pop_behavior(struct nk_context *)
float h
Definition: nuklear.h:457
struct nk_color selected_normal
Definition: nuklear.h:3597
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
NK_API void nk_layout_row_template_end(struct nk_context *)
Definition: nuklear.h:2162
Definition: nuklear.h:1842
struct nk_style_button dec_button
Definition: nuklear.h:3567
float rounding
Definition: nuklear.h:3760
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3515
NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a)
struct nk_style_edit edit
Definition: nuklear.h:3632
NK_API int nk_combo_string(struct nk_context *, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size)
struct nk_style_toggle option
Definition: nuklear.h:3785
struct nk_panel pan
Definition: nuklear.h:4103
Definition: nuklear.h:678
NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
struct nk_buffer_marker marker[NK_BUFFER_MAX]
Definition: nuklear.h:2683
NK_API int nk_combo_begin_image_text(struct nk_context *, const char *selected, int, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:2954
Definition: nuklear.h:2155
char string[1]
Definition: nuklear.h:3118
Definition: nuklear.h:2168
int heuristic(Location a, Location b)
Definition: findpath.cpp:58
nk_plugin_copy copy
Definition: nuklear.h:2814
Definition: nuklear.h:3382
struct nk_vec2 size offset
Definition: nuklear.h:462
struct nk_style_item normal
Definition: nuklear.h:3520
NK_API int nk_selectable_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int *value)
Definition: nuklear.h:666
struct nk_style_button node_minimize_button
Definition: nuklear.h:3696
Definition: nuklear.h:3855
nk_handle userdata
Definition: nuklear.h:3409
unsigned short line_thickness
Definition: nuklear.h:3055
NK_API int nk_check_text(struct nk_context *, const char *, int, int active)
short y
Definition: nuklear.h:3114
struct nk_text_edit text_edit
Definition: nuklear.h:4154
NK_API int nk_style_push_style_item(struct nk_context *, struct nk_style_item *, struct nk_style_item)
Definition: nuklear.h:2170
NK_API void nk_textedit_delete(struct nk_text_edit *, int where, int len)
int slot
Definition: nuklear.h:3840
NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed)
struct nk_style_item active
Definition: nuklear.h:3418
char name_string[NK_WINDOW_MAX_NAME]
Definition: nuklear.h:3972
Definition: nuklear.h:4130
typedef int(ENET_CALLBACK *ENetInterceptCallback)(struct _ENetHost *host
Definition: nuklear.h:2975
struct nk_page_element * prev
Definition: nuklear.h:4110
short x
Definition: nuklear.h:458
enum nk_anti_aliasing shape_AA
Definition: nuklear.h:984
Definition: nuklear.h:1831
struct nk_rect clip
Definition: nuklear.h:3128
struct nk_panel * layout
Definition: nuklear.h:3978
int length
Definition: nuklear.h:3117
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
struct nk_color left
Definition: nuklear.h:3013
Definition: nuklear.h:2992
struct nk_str string
Definition: nuklear.h:2846
nk_handle userdata
Definition: nuklear.h:3637
Definition: nuklear.h:466
Definition: nuklear.h:2004
#define const
Definition: zconf.h:196
short char_storage
Definition: nuklear.h:2821
short redo_char_point
Definition: nuklear.h:2830
int sel_start
Definition: nuklear.h:3949
struct nk_command header
Definition: nuklear.h:2984
short x
Definition: nuklear.h:3103
struct nk_clipboard clip
Definition: nuklear.h:4135
float border_cursor
Definition: nuklear.h:3560
NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color)
struct nk_vec2 content_padding
Definition: nuklear.h:3681
unsigned short line_thickness
Definition: nuklear.h:2995
enum nk_style_item_type type
Definition: nuklear.h:3378
NK_API void nk_label_colored(struct nk_context *, const char *, nk_flags align, struct nk_color)
struct nk_style_item active
Definition: nuklear.h:3716
Definition: nuklear.h:3956
Definition: nuklear.h:471
struct nk_color text_normal
Definition: nuklear.h:3426
Definition: nuklear.h:690
struct nk_color label_hover
Definition: nuklear.h:3664
Definition: nuklear.h:2164
NK_API int nk_check_label(struct nk_context *, const char *, int active)
struct nk_command header
Definition: nuklear.h:3061
NK_API void nk_window_set_bounds(struct nk_context *, struct nk_rect bounds)
nk_layout_format
Definition: nuklear.h:475
struct nk_color bar_filled
Definition: nuklear.h:3490
Definition: nuklear.h:2171
Definition: nuklear.h:3414
Definition: nuklear.h:452
Definition: nuklear.h:3122
short y
Definition: nuklear.h:456
NK_API void nk_end(struct nk_context *ctx)
NK_API int nk_menu_begin_symbol(struct nk_context *, const char *, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_strfilter(const char *text, const char *regexp)
NK_API void nk_combobox_string(struct nk_context *, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size)
nk_text_width_f width
Definition: nuklear.h:2486
char buffer[NK_MAX_NUMBER_BUFFER]
Definition: nuklear.h:3958
Definition: nuklear.h:494
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3440
NK_API char * nk_str_get(struct nk_str *)
NK_UINT8 nk_byte
Definition: nuklear.h:396
#define NK_CHART_MAX_SLOT
Definition: nuklear.h:3811
struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]
Definition: nuklear.h:2825
unsigned short h
Definition: nuklear.h:2997
Definition: nuklear.h:2681
Definition: nuklear.h:460
Definition: nuklear.h:493
NK_API int nk_str_append_str_runes(struct nk_str *, const nk_rune *)
NK_API struct nk_color nk_rgba_fv(const float *rgba)
struct nk_config_stack_float floats
Definition: nuklear.h:4079
nk_uint x
Definition: nuklear.h:463
struct nk_style_button tab_maximize_button
Definition: nuklear.h:3693
#define NK_UNUSED(x)
Definition: nuklear.h:4178
int down
Definition: nuklear.h:3180
Definition: nuklear.h:3377
NK_INT16 nk_short
Definition: nuklear.h:397
short x
Definition: nuklear.h:3004
NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context *)
Definition: nuklear.h:1997
NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context *)
NK_API struct nk_rect nk_window_get_content_region(struct nk_context *)
NK_API int nk_select_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int value)
float grow_factor
Definition: nuklear.h:2691
struct nk_vec2 uv
Definition: nuklear.h:979
nk_uint * scroll_pointer
Definition: nuklear.h:1805
Definition: nuklear.h:452
Definition: nuklear.h:471
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
unsigned int seq
Definition: nuklear.h:4168
Definition: nuklear.h:454
int select_end
Definition: nuklear.h:3962
nk_text_edit_mode
Definition: nuklear.h:2838
struct nk_config_stack_color colors
Definition: nuklear.h:4082
struct nk_edit_state edit
Definition: nuklear.h:3984
struct nk_color label_active
Definition: nuklear.h:3665
NK_API void nk_style_from_table(struct nk_context *, const struct nk_color *)
int sel_end
Definition: nuklear.h:3950
#define NK_UINT8
Definition: nuklear.h:340
struct nk_input input
Definition: nuklear.h:4132
NK_API int nk_button_label(struct nk_context *, const char *title)
#define NK_MAX(a, b)
Definition: nuklear.h:316
const struct nk_user_font * font
Definition: nuklear.h:3775
float w
Definition: nuklear.h:3882
enum nk_button_behavior button_behavior
Definition: nuklear.h:4137
struct nk_context * ctx
NK_API int nk_button_text(struct nk_context *, const char *title, int len)
NK_API void nk_menubar_begin(struct nk_context *)
NK_API int nk_style_push_float(struct nk_context *, float *, float)
#define NK_PTR_TO_UINT(x)
Definition: nuklear.h:4208
#define NK_FONT_STACK_SIZE
Definition: nuklear.h:4026
NK_API int nk_combo_item_label(struct nk_context *, const char *, nk_flags alignment)
NK_API int nk_button_image_label(struct nk_context *, struct nk_image img, const char *, nk_flags text_alignment)
NK_API int nk_button_image_text(struct nk_context *, struct nk_image img, const char *, int, nk_flags alignment)
Definition: nuklear.h:673
Definition: nuklear.h:2817
NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color)
NK_API int nk_str_insert_str_char(struct nk_str *, int pos, const char *)
struct nk_vec2i points[1]
Definition: nuklear.h:3088
Definition: nuklear.h:2138
struct nk_vec2 padding
Definition: nuklear.h:3501
NK_API int nk_menu_begin_label(struct nk_context *, const char *, nk_flags align, struct nk_vec2 size)
unsigned char grabbed
Definition: nuklear.h:3175
NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color)
unsigned char mode
Definition: nuklear.h:3952
NK_API int nk_style_pop_flags(struct nk_context *)
NK_API int nk_button_symbol_text_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API struct nk_color nk_rgb_hex(const char *rgb)
struct nk_style_item hover
Definition: nuklear.h:3658
nk_symbol_type
Definition: nuklear.h:489
NK_API struct nk_color nk_rgb_bv(const nk_byte *rgb)
NK_API int nk_str_insert_str_utf8(struct nk_str *, int pos, const char *)
struct nk_allocator pool
Definition: nuklear.h:2685
NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region)
struct nk_color text_background
Definition: nuklear.h:3429
short cy
Definition: nuklear.h:3062
Definition: nuklear.h:687
NK_API void nk_plot_function(struct nk_context *, enum nk_chart_type, void *userdata, float(*value_getter)(void *user, int index), int count, int offset)
struct nk_vec2 image_padding
Definition: nuklear.h:3405
NK_API nk_rune nk_str_rune_at(const struct nk_str *, int pos)
struct nk_scroll offset
Definition: nuklear.h:3883
NK_API int nk_style_pop_font(struct nk_context *)
struct nk_style_item hover
Definition: nuklear.h:3417
nk_command_clipping
Definition: nuklear.h:3121
tuple output
Definition: gtest_output_test.py:321
Definition: nuklear.h:3183
int columns
Definition: nuklear.h:3862
unsigned short r
Definition: nuklear.h:3054
int text_len
Definition: nuklear.h:3186
NK_INT32 nk_int
Definition: nuklear.h:399
NK_API int nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
float border
Definition: nuklear.h:3603
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
Definition: nuklear.h:698
NK_API void nk_textedit_redo(struct nk_text_edit *)
NK_API void nk_menu_close(struct nk_context *)
Definition: nuklear.h:472
NK_API struct nk_vec2 nk_rect_size(struct nk_rect)
Definition: nuklear.h:671
struct nk_style_item background
Definition: nuklear.h:3644
NK_API void nk_str_init(struct nk_str *, const struct nk_allocator *, nk_size size)
NK_API struct nk_image nk_image_id(int)
short y
Definition: nuklear.h:3004
struct nk_color color
Definition: nuklear.h:3057
Definition: nuklear.h:3851
NK_API int nk_combo_begin_image(struct nk_context *, struct nk_image img, struct nk_vec2 size)
Definition: nuklear.h:2940
#define nk_vec2_len_sqr(a)
Definition: nuklear.h:4192
struct nk_style_button inc_button
Definition: nuklear.h:3633
void(* draw_begin)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3410
struct nk_style_item active
Definition: nuklear.h:3548
struct nk_command header
Definition: nuklear.h:3037
Definition: nuklear.h:2175
Definition: nuklear.h:3369
NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color)
NK_API void nk_combo_end(struct nk_context *)
Definition: nuklear.h:2953
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
Definition: nuklear.h:3818
nk_size calls
Definition: nuklear.h:2697
NK_API void nk_input_char(struct nk_context *, char)
Definition: nuklear.h:3001
NK_API void nk_color_dv(double *rgba_out, struct nk_color)
struct nk_page_element win[1]
Definition: nuklear.h:4116
#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1)
Definition: nuklear.h:4185
NK_API struct nk_vec2 nk_vec2v(const float *xy)
NK_API int nk_tooltip_begin(struct nk_context *, float width)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3441
NK_API struct nk_rect nk_recti(int x, int y, int w, int h)
NK_API struct nk_panel * nk_window_get_panel(struct nk_context *)
struct nk_vec2 menu_padding
Definition: nuklear.h:3770
struct nk_color label_normal
Definition: nuklear.h:3619
nk_size offset
Definition: nuklear.h:2678
nk_show_states
Definition: nuklear.h:470
struct nk_color color
Definition: nuklear.h:3383
struct nk_style_item pressed
Definition: nuklear.h:3448
NK_API int nk_style_pop_color(struct nk_context *)
NK_API struct nk_color nk_rgba_iv(const int *rgba)
unsigned char single_line
Definition: nuklear.h:3953
struct nk_color selected_hover
Definition: nuklear.h:3598
NK_API void nk_chart_end(struct nk_context *)
short x
Definition: nuklear.h:3046
struct nk_command_buffer * buffer
Definition: nuklear.h:3901
float a
Definition: nuklear.h:454
struct nk_color menu_border_color
Definition: nuklear.h:3746
NK_API int nk_menu_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
Definition: nuklear.h:465
Definition: nuklear.h:1865
Definition: nuklear.h:3847
NK_API int nk_combo_begin_symbol_label(struct nk_context *, const char *selected, enum nk_symbol_type, struct nk_vec2 size)
Definition: nuklear.h:472
#define NK_ALIGN_PTR_BACK(x, mask)
Definition: nuklear.h:4219
NK_API int nk_style_push_vec2(struct nk_context *, struct nk_vec2 *, struct nk_vec2)
nk_heading
Definition: nuklear.h:465
#define nk_vec2_muls(a, t)
Definition: nuklear.h:4193
nk_style_colors
Definition: nuklear.h:2136
NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context *)
NK_API int nk_menu_begin_text(struct nk_context *, const char *title, int title_len, nk_flags align, struct nk_vec2 size)
struct nk_color background
Definition: nuklear.h:3112
struct nk_vec2i end
Definition: nuklear.h:2987
nk_handle userdata
Definition: nuklear.h:3130
Definition: nuklear.h:491
NK_API struct nk_rect nk_rectiv(const int *xywh)
unsigned short h
Definition: nuklear.h:461
struct nk_color border_color
Definition: nuklear.h:3689
NK_API struct nk_vec2 nk_widget_size(struct nk_context *)
NK_API void nk_layout_row_push(struct nk_context *, float value)
nk_flags text_alignment
Definition: nuklear.h:3430